MSDE FunClub
Microsoft Data Engine FunClub
MSDE技術者向けメーリングリスト過去ログ[1421]番
 
[TOP]>[MSDE技術者向けメーリングリスト過去ログ(1421番)]>[ウィンドを閉じる]
 
SQLServer2005時代でも
開発の基本は T-SQL
上巻で T-SQL の基礎作り
 
SQLServer2005時代でも
運用の基本はバックアップ
下巻でバックアップ手法を学びましょう
PASSJ人気コンテンツで学んだ後は下巻でさらなる学習を!
 
ウィンドを閉じる
MSDE/SQLServer FAQ
MSDE / MSDE2000 
技術情報サポート
初心者向け
メーリングリスト
過去ログの表示
技術者向け
メーリングリスト
過去ログの表示
メーリングリスト
活動状況の
表示
MSDE TOP メニュー
MSDEトップメニューに移動します
 

 
SQL インジェクション対策( sp_executesql ストアドの活用)

Date: Thu, 7 Jul 2005 14:26:58 +0900
From: "Akira Horikawa" <who@example.ne.jp>


堀川です、こんにちは

価格COMでは被害者側から正確な情報提供が無かったですが、
犯人側からの話によれば、『SQLインジェクション』という方法が
使われたようです。

SQLインジェクション攻撃に気づかない企業は山のようにある
http://itpro.nikkeibp.co.jp/free/NPC/NEWS/20050706/164102/


WebアプリケーションのCGIプログラムを開発している環境が、
UNIXであれば、外部から渡されるパラメータ文字列の中に
パイプ記号やリダイレクト記号などが含まれ、/etc/passwd等の
重要なファイルを簡単に盗まれてしまうので、十分なパラメータ
検査が必要だと徹底的に教え込まれます。

そのような経験をした技術者であれば、データベースと連携する
SQL文を書くときも、不正な文字列等が含まれていないかどうか
の検査を自然に行ないます。

本来このような検査は、UNIXのCGI開発の経験が無くても、当然の
こととして行なわなければいけませんが、大事なことは、外部から
渡されるパラメータの中に、
   『仕様外の予想もできない内容が含まれることがある』
ということを自覚し、
     そのような例外を除去するような検査プログラム
を書いているかどうかだと思います。

 外部から渡されるパラメータの内容が全部インチキであることを
前提にシステムを作っているかどうかの姿勢が大事です。


 外部から渡されるパラメータを信用して、そのままSQL文を組み
立てているようなプログラムがあるときは、十分にご注意下さい。

  前回記事『SQL インジェクションについて』
 http://www.horikawa.ne.jp/cgi-bin/showlog.cgi?kd=2&no=1522
でも触れていますが、

  SQL="SELECT * FROM TBL WHERE( ID="  +  Param$ + ")"

このような感じで、外部から与えられる文字列(Param$)から
SQL文の文字列を組み立てている場合は要注意です。

 SELECT文以外の命令でも、同様に十分な検査が必要です。

 SQL="DELETE FROM TBL WHERE( ID=" + Param$ + ")"

のときに、Param$の入力が

                                '1  or (1=1)'

と入力されると、全部のレコードが削除されます。

--
--Transact-SQLの例題です
--
CREATE TABLE #TMP( ID INT )
   INSERT INTO #TMP(ID) VALUES(1)
   INSERT INTO #TMP(ID) VALUES(2)
   INSERT INTO #TMP(ID) VALUES(3)
   INSERT INTO #TMP(ID) VALUES(4)
   INSERT INTO #TMP(ID) VALUES(5)

DECLARE @SQL       VARCHAR(256)
DECLARE @PARAM  VARCHAR(256)

SELECT @PARAM = '1'
SELECT @SQL = 'DELETE FROM #TMP WHERE( ID =  ' + @PARAM + ')'
SELECT * FROM #TMP
EXEC(@SQL)
SELECT * FROM #TMP

DROP TABLE #TMP


上記プログラムの@PARAMへの代入を

       SELECT @PARAM = '1  OR (1=1)'

と書き換えて、実行してみて下さい。

全部のレコードが削除されます。



本来@PARAMの内容が数字であるべきところに、論理演算子の
ORが含まれた文字列が渡される可能性を予想もしていなかった
ことに、問題が潜んでいます。

データベースシステム側に問題があるのではなく、外部から渡される
パラメータを100%信用した、このプログラムを作成した人間が悪いです。


皆様のシステムの中で、何の検査もせずに、ただ単純に、SQL文の
文字列を組み立てているような箇所があれば、その箇所には、
SQLインジェクションの問題が発生する可能性が潜んでいます。



SQLインジェクションを簡単に防ぐ方法は、SQL文の実行をEXECUTE命令
を使わずに、sp_executesql ストアドプロシージャに置き換えることです。

上記例題プログラムを次のように書き換えます。
変数名を多少変えています。

CREATE TABLE #TMP( ID INT )
   INSERT INTO #TMP(ID) VALUES(1)
   INSERT INTO #TMP(ID) VALUES(2)
   INSERT INTO #TMP(ID) VALUES(3)
   INSERT INTO #TMP(ID) VALUES(4)
   INSERT INTO #TMP(ID) VALUES(5)

DECLARE @SQL                   NVARCHAR(256)
DECLARE @PARAM_DEF       NVARCHAR(256)
DECLARE @PARAM_VALUE     VARCHAR(256)

SELECT @PARAM_VALUE = '1'

SELECT @SQL =  N'DELETE FROM #TMP WHERE( ID = @SET_PARAM )'
SELECT @PARAM_DEF = N'@SET_PARAM   INT'

SELECT * FROM #TMP

EXEC sp_executesql
           @stmt             = @SQL ,
           @params         = @PARAM_DEF ,
           @SET_PARAM = @PARAM_VALUE

SELECT * FROM #TMP

DROP TABLE #TMP

上記プログラムの中で、

   SELECT @PARAM_VALUE = '1'

の部分を

   SELECT @PARAM_VALUE = '1 OR (1=1)'

にして、実行して見てください。


サーバー : メッセージ 8114、レベル 16、状態 1、行 0
型 varchar から型 int への変換エラー。

データベースサーバーから、エラーが発生します。

レコードが全部削除されるよりは、エラーが発生するのがまだマシです。
ただこのようなエラーが発生することを、これを呼び出したCGIプログラムは
想定しているでしょうか?

やはり、SQL文の中で、正しい文字列かどうか、検査するようにしてください


------------------------------------
(株)日本技術ソフト開発
        堀川 明  (Akira Horikawa)
    07月07日(木曜日) 14時25分記
        mailto:who@example.ne.jp
        http://www.horikawa.ne.jp/msde/






[MSDE/SQLServerに関して、今、どんなことにお困りですか?]
よろしければお困りの内容を、電子メールで教えて下さい。
質問を電子メールで作成する


[ウィンドを閉じる]

[MSDE/SQLServer FAQ ]

[MSDE / MSDE2000 技術サポート情報一覧]

MSDE TOP ページに移動する

 
 
 
 
 
 
 
MSDE FunClubに関するご意見・ご要望等ございましたら、
msdefun@horikawa.ne.jp までご連絡下さい。
MSDEを始めとする各種データベースシステムの開発、コンサルタントに関するご要望等は、
msdedev@horikawa.ne.jp までご連絡下さい。