SQLインジェクションなどの対策:特殊文字の無害化

はじめに
 2005年7月6日、中国人留学生(27歳)が不正アクセス禁止法違反で逮捕された。「カカクコム」などのサイトから、「SQLインジェクション」と呼ぶ手口で個人情報を盗んだと見られ、世間を騒がせました。
 本稿では、このような脆弱性が発生する原因と対策(注意点)について述べます。


根本原因は特殊文字の存在
 下記のようなログイン認証画面を例とします。

 上記の入力を受け、つぎのSQL文で評価しているとします。
 「Select * from Table where ID='admin' AND Password='123456'」


 上記のように、Password欄にシングルクォートを入れられても、システムに何の対策もとられていないのなら、このSQL文は正しいものと見なされます。
 「Select * from Table where ID='admin' AND Password='' OR 'X'='X'」

 すなわち、パスワード知らなくてもログインできてしまうなど、とんでもないことが起きてしまいます。

 このような脆弱性が発生した理由は、SQL文の文字列の区切り文字であるシングルクォートを正しく処理していないことにあります。

SQL文の中でシングルクォートをデータとして扱うには、シングルクォートを2つ並べエスケープ文字として扱うことが規約です。
 「Select * from Table where ID='admin' AND Password=''' OR ''X''=''X'」

 上記のように、SQL文の特殊文字であるシングルクォートは、サニタイジング(無害化)をする処理が必要です。 逆に、シングルクォートをサニタイジングしていないと、「SQLインジェクション」などの攻撃に耐えらません。

 HTMLでも、データベースのSQL文と同じように、特殊文字のサニタイジングが必要です。この不備を突いた攻撃で有名なのが「クロスサイトスクリプティング」です。
 例えば、下記のように「<s>admin</s>」と入力されたとします。


 結果は下記のように、<s>がタグの字消し線として解釈され、サニタイジングされていないのがわかります。


特殊文字のサニタイジングは、Xcuteで必要か?
 「Xcuteの開発者は、特殊文字のサニタイジングは必要ありません。Xcute側で全て対処している。」と言い切れるなら良いのですが、Xcute側で基本的には対処しているが、対処できないコマンドもあると言うことです。
 以下、対処していない、あるいは、対処出来ないコマンドについて述べます。

1)SQL文の中でシングルクォート
 データベースへの命令は、XcuteでもSQL文を使い、R2C8セルなどに指定されるFilterChg_SQLなどのコマンドで、実際に発行されるSQL文を組み立てます。
 通常のFilterコマンドは、Xcuteが構文を組み立てますので、Xcute側でサニタイジングが可能であり、実際に行っています。
 しかし、Chg_SQLEXT_SQLFilter()コマンドでは、Xcuteは忠実にSQL文のWhere句を置き換えるだけで、内部でサニタイジングはしておりません。
 繰り返すと、Chg_SQLEXT_SQLFilter()コマンド使う場合は、サニタイジングあるいは、それと同等の処置をしないといけないと言う事です。

2)HTML文の中の特殊文字
 HTML文の中の特殊文字も、1)項と同様に、Xcute側でサニタイジングを行っていますが、されない場合もあります。
 サニタイジングが行われているのは、Excelの印刷範囲内が対象となり、タグ差込を行うときは注意が必要です。 タグ差込でも、Excelの入力規則を使った場合は問題ありません。
 問題となるのは、「入力された文字列を使って<Font>タグや、<A>タグ、<Input>タグを差し込む」場合です。


Xcuteでの具体的な対処法
1)サニタイジング(無害化)処理を組み込む
 この方策は、教科書的な対処方法です。 手間が掛かりますが、特殊文字の置換を行うことです。
SQL文中におけるシングルクォートの対策として、Chg_SQLFilter()コマンドを使う時は、Substituteシート関数などを使って、1つのシングルクォートを、2個のシングルクオートに置き換えることです。

2)proles.iniファイルのNoSetCharを設定
 Xcuteはブラウザの入力値をExcelにSetコマンドで使って戻していますが、戻す文字を制限することができます。 NoSetCharに設定された文字列は、Excelに渡されず、つぎのエラーをブラウザに返します。
 NoSetCharによる対処は、漏れが発生せず極めて強力です。 XCuteサーバをインターネットに公開する場合は、NoSetChar=<>' (小なり、大なり、シングルクォート)は必ず指定してください。

 ついでながら、インターネットに公開する場合は、proles.iniファイル中のDebugDebug=0としてください。
Debug=1では、データベースのエラーがそのままブラウザに表示されてしまいます。 Debug=0は、Error.logに、エラーは書き出されても、ブラウザには表示されません。


最後に
SQLインジェクション」が発生した「カカクコム」のサイトは、データベースのエラーがそのままブラウザに表示され、テーブル名やフィールド名が盗み見られていたと報告されています。

セキュリティの情報はインターネットですぐ検索でき、その代表例は下記に示します。
http://www.ipa.go.jp/security/awareness/vendor/programmingv1/a01_02.html
http://www.atmarkit.co.jp/fsecurity/rensai/webhole01/webhole01.html

以上