【関連記事】
本内容についてのアップデート記事を公開しています。あわせてご確認ください(編集部)
Security&Trustウォッチ(60)
今夜こそわかる安全なSQLの呼び出し方 〜 高木浩光氏に聞いてみた
http://www.atmarkit.co.jp/fsecurity/column/ueno/60.html
Webアプリケーションに対する攻撃手法の1つであるSQLインジェクションの存在は、かなり広く知られるようになった。しかし、その対策はまだ本当に理解されていないように思える。フォームから渡された値の特殊文字をエスケープしたり、PHPのmagic_quotes_gpcといった自動エスケープ機能をオンにするだけで対策したつもりになっていないだろうか。
基本はもちろん、セカンドオーダーSQLインジェクションやマルチバイト文字を利用したSQLインジェクションの攻撃パターンや、その対策などを見直してみよう。
SQLインジェクションの基本
SQLインジェクション(SQL Injection)はWebアプリケーションに対する攻撃手法の1つで、SQLを使って不正にデータベースを操作することを目的としている。SQLというのは、データベースを操作するために一般的に使われている言語である。
このSQLインジェクションによる攻撃は、今日の脆弱性報告ブーム(?)の一端を担う手法であり、情報処理推進機構(IPA)に届け出られたWebアプリケーションの脆弱性関連情報(2006年9月まで)によると、第1位(41%)のクロスサイトスクリプティングに続いて、第2位(21%)がSQLインジェクションである。Webアプリケーションに携わっていて、この言葉を知らない人はかなり少なくなった(と思いたい)。
SQLインジェクションの脆弱性を持ったアプリケーションのよくある例としては次のようなものである。
これは、ユーザー名とパスワードを入力してログインする処理の一部である。uidとpwdの組み合わせが、データベースのものと一致すると認証するという仕組みだとする。
SELECT * FROM user WHERE uid='$uid' AND pwd='$pwd'
ユーザーからの入力は、ユーザー名が$uid、パスワードが$pwdに渡されるものとする。ここで、以下のような入力があった場合の挙動を考えてみよう。
$uid : ueno
$pwd : ' OR 'A'='A
これを入力するとSQLは以下のようになる。
SELECT * FROM user WHERE uid='ueno' AND pwd='' OR 'A'='A'
これが実行されるとORの後は常に真なので、パスワードが異なるにもかかわらず認証されてしまうという現象が起きてしまう。
ここで取り上げた認証の回避以外にも、SELECTやDELETEといったSQLを用いた不正なデータベース操作が実行できてしまう可能性もある。テーブル名などが分からない場合でも、サブクエリーを利用して存在するテーブルが検索できる場合もある。
この問題の対策としては、入力値には半角英数字のみを許可するよう制限する方法や、以下の例のようにSQLで使える特殊文字をエスケープして対処するという方法が一般的になっている。
' → ''
\ → \\
【注】
「\」を拡張してるRDBMSでは「\\」とエスケープする必要がある
この対策自体の方向性は正しいのだが、SQLインジェクションを理解していないため、対策が漏れている場合がある。
セカンドオーダーSQLインジェクション
SQLインジェクション対策として、入力値を適切にエスケープするという対策を行うが、この「入力値」が何なのか間違えていたり、チェックが漏れている場合がしばしば見受けられる。また、HTMLを生成する段階でエスケープすればよいと考えている人も見受けられるが、それも間違いである。
フォームに入力可能な部分だけが対策個所ではない。不正な入力の可能性を考える必要があるのは、GETやPOSTなどのクエリーやCookieの値、HTTPヘッダなど、HTTP経由で送られてくるもの“すべて”と、それに加えてデータベースやファイルなどに保存されたデータを呼び出す際にも対策を怠ってはならない。ここに問題があると、セカンドオーダーSQLインジェクションと呼ばれる脆弱性を持つことになる。
次のような$uidの値を受け付けたときに「'」を「''」としてエスケープしてデータベースに保存したとする。
$uid : ueno' union……
文字列をエスケープして登録しても、次にデータベースから呼び出した際には、エスケープされていない元のデータが呼び出されることになる。この文字列をSQLに使用してしまうと、そこでSQLインジェクションが成立してしまう。
入力した時点ですぐに効力を発揮せずに、次にアプリケーションで利用されたときに効力を発揮するこの攻撃をセカンドオーダーSQLインジェクションと呼ぶ。
シングルクオーテーションを使わないSQLインジェクション
SQLインジェクション対策というと、「'」(シングルクオーテーション)の扱いばかりが注目されるが、「'」を使わなくても成立する攻撃もある。
以下の例を見てみよう。
SELECT name FROM user where uid = '$uid' AND age > $age
このSQLに渡される$uidと$ageの特殊文字は、適切にエスケープされているとしよう。ここに次のような値を渡す。
$uid : ueno
$age : 31 UNION……
これを入力するとSQLは以下のようになる。
SELECT name FROM user where uid = 'ueno' AND age > 31 UNION……
これを実行するとUNION以降のSQLも実行されてしまうことになる。この問題は、ageの値がシングルクオーテーションで囲われていなかったことが原因である。以下のように囲われていれば、この問題は起きることがない(もちろん、数値以外は受け付けないという前段階の処理も欲しい)。
SELECT name FROM user where uid = '$uid' AND age > '$age'
マルチバイト文字の問題
マルチバイト文字というのは、シフトJISやEUC-JPなどの2バイト文字などのことを指す。このマルチバイト文字を適切に処理しないと思わぬところでSQLインジェクションが発生することがある。
PHPならばaddslashes()といった関数を使って、フォームから受け取った入力値に含まれる「'」を「\'」と置換するなどの処理をしてSQLインジェクションによる攻撃を回避しようとするかもしれない。
以下の例を見てみよう。
\x97' OR A=A → 予' OR A=A
「\x97' OR A=A」を前述のように「'」を「\'」とエスケープして処理してみると、「予' OR A=A」と変換されることがある。これはシフトJISの環境で発生する現象だ。
この現象を詳しく見てみよう。
\x97' → \x97\'
ポイントとなるのは「\x97'」の部分で、これの「'」をエスケープするために「\'」と置換すると「\x97\'」となる。
「\'」の部分もエンコードしてみると、「\x5C\x27」となり、全体では「\x97\x5C\x27」となる。
\x97\x5C\x27 → 予'
これを文字に戻すと、手前から「\x97\x5C」が2バイト文字として扱われて「予」となり、「\x27」が1バイト文字として扱われてしまい「'」となる。
予' OR A=A
結果として、「'」を「\'」とエスケープしたはずなのに、「'」が残ってしまうという現象が起きる。
シフトJISは2バイト文字だが、中には2バイト目に1バイト文字の文字コードを含んだ文字がある。そのためにこのような現象が起きる。
\x94\x5C → 能
\x95\x5C → 表
\x96\x5C → 暴
「\x97'」の組み合わせ以外にも多数のパターンが考えられる。「'」を「''」とエスケープしている場合にも同様の現象が起きる可能性がある。
これを回避するためには、クライアント側の文字コードにシフトJISを使うのをやめてEUC-JPなどを使うという方法がよい。
しかし、諸事情により文字コードを変更できないという場合もあるかもしれない。その場合には、半端な1バイト文字を受け付けない処理を書くか、以下のようにマルチバイトを扱う関数を通して、文字コードを整理するという手もある。
- Perlの場合 :Encode::from_to($str, "sjis","sjis");
- PHPの場合 :mb_convert_encoding($str, 'SJIS', 'SJIS')
PHPなどで用意されているmagic_quotes_gpcといった自動エスケープの機能が有効になっている場合には特に注意が必要である。思いがけないところで、このような現象が発生する余地を残している可能性がある。できるだけ全体に有効な自動エスケープの機能は無効にして、必要な個所を適切にエスケープ処理することが重要である。
このマルチバイトの問題はSQLインジェクション以外に、クロスサイトスクリプティングなどの攻撃にも利用できるので対策の際には見落としがないように注意していただきたい。
【関連リンク】マルチバイトの落とし穴マルチバイトの落とし穴 http://www.atmarkit.co.jp/fsecurity/rensai/hoshino10/hoshino01.html
SQLインジェクション対策
SQLインジェクションがはやり始めた2005年ごろに比べると、その手口は凝ったものになりつつある。今後はさらに巧妙な手口が現れてくる可能性もある。SQLインジェクション対策のポイントを見直してみよう。
●Webアプリケーションの対策
- SQLを埋め込むところで特殊文字を適切にエスケープ
- シフトJISの場合には1バイト文字を整理
- SQLの記述をなくすためにO/R(Object/Relational)マッピングを活用
- 攻撃者に役立つ情報を与えないために、不要なエラーメッセージ(データベースが出力するエラーなど)の表示を抑止
- バインドメカニズムの利用
Webアプリケーション周りの対策
- WAF(Web Application Firewall)による不正な文字の検出・防御(もしくは、ホワイトリストによる通過の許可)
- IDS(Intrusion Detection System)、IPS(Intrusion Prevention System)などによる不正な文字の検出・防御
データベースの対策
- アカウント分離と権限の最小化による適切なアクセス制御
- 管理者アカウントなどの越権から守るために必要個所を適切に暗号化
- 万が一の侵入の際に検証可能なようにログを適切に取得
いまさらソースコードに手を入れることはできないが、システムは生かさなければならないという状況では、WAFの導入は効果があるはずである。
また、どれも1つだけで決定的な手段というわけではないので、対策の際には併用してセキュリティレベルを高めることをお勧めする。
今回はSQLインジェクションに特化して説明しているので、対策もSQLインジェクション中心に行ってきた。もちろん、クロスサイトスクリプティングなどほかのセキュリティ対策も併せて実施していただきたい。
Profile
上野 宣(うえの せん)
株式会社トライコーダ代表取締役
ネットワーク・セキュリティ監査、セキュリティ対策・運用改善コンサルティングを主な業務としている。
情報セキュリティを世に広げるべく、講演や執筆活動とさまざまな方面で活動中。近著に「今夜わかるメールプロトコル」、「今夜わかるTCP/IP」、「今夜わかるHTTP」(共に翔泳社)がある。個人ブログは「うさぎ文学日記」
●修正履歴
【2006/11/2】
本文中のSQLで使える特殊文字をエスケープ例について、注記として「「\」を拡張してるRDBMSでは「\\」とエスケープする必要がある」を追記いたしました。
また、セカンドオーダーSQLインジェクションの項におけるエスケープ例を「\'」から「''」へ修正いたしました。
【2006/11/6】
SQLインジェクション対策、Webアプリケーションの対策について、「入力値のSQLの特殊文字を適切にエスケープ 入力値=プログラム(プロセス)に外部から入ってくるもの 」を「SQLを埋め込むところで特殊文字を適切にエスケープ」に修正し、「バインドメカニズムの利用」を追記いたしました。
- 今夜こそわかる安全なSQLの呼び出し方 〜 高木浩光氏に聞いてみた
- 「わざと脆弱性を持たせたWebアプリ」で練習を
- Perl Mongersはセキュリティの夢を見るか?
- 誰がシステムのセキュリティを“大丈夫”にするのか
- 技術は言葉の壁を越える! Black Hat Japan 2008&AVTokyo2008(後編)
- 技術は言葉の壁を越える! Black Hat Japan 2008&AVTokyo2008(前編)
- キャンプに集まれ! そして散開!
- 売り上げ重視か、それともセキュリティ重視か!? 「安全なウェブサイト運営入門」
- CeCOS IIにみるネット犯罪のもう一方の側面
- セキュリティ対策の行き着くところは……最終手段? 京都に究極のセキュリティ対策を見た
- 人はオレを情報の破壊神と呼ぶ せめて、ハードディスクの最期はこの手で……
- セキュリティ社会科見学:インターネット物理モデルでセキュリティを考えた
- セキュリティ自由研究:この夏、グミ指を作ってみないか
- Webアプリケーションを作る前に知るべき10の脆弱性
- セキュリティを教える人に知ってほしい 基本が詰まった1冊
- セキュリティのバランス感覚を養うための1冊
- 暗号化仮想ドライブで手軽にファイルを暗号化
- Windows管理者必携、Sysinternalsでシステムを把握する
- 今夜分かるSQLインジェクション対策
- 「取りあえず管理者アカウントで」という思考停止はもうやめよう
- CSSクロスドメインの情報漏えいの脆弱性「CSSXSS」とは
- 偽装メールを見破れ!(後編)
- 偽装メールを見破れ!(前編)
- メールは信頼できても信用できない
- 危機管理体制を整えよう! 個人情報漏えい後の対応ガイドライン
- メールアドレスを漏えいから守る方法
- 「Whoppix」を使ってペネトレーションテストをやろう
- 「ぼくはまちちゃん」 ――知られざるCSRF攻撃
- 25番ポートの攻防
- 平田です。届いてますか?
- 魔法の鍵と最後の鍵
- 個人情報保護法を論理的に読み解く
- 安全確保のために東京は明るく! 大阪は暗く!
- 言論の自由とセキュリティコミュニティ
- 標的にされる無防備なコンピュータ
- セキュリティ担当者には想像力が必要
- 端末を持ち歩くことの危険を意識せよ! 〜 「ノートPC=自動車」論 〜
- 脆弱性のあるサイトとセキュリティ技術者の関係
- いまこそ一般教養としてセキュリティを!
- 大事なことは製品でもなく知識でもなく……
- 治安の悪化で改めて痛感したこと
- Blasterがもたらした多くの“メリット”
- 企業でのセキュリティ資格の意味合いは?
- 人はミスをするものと思え、故に事前対策が重要
- オレオレ詐欺に学ぶソーシャル対策
- あらゆる人にセキュリティ教育を
- 猛威を振るうSARSウイルスに思ったこと
- 痛い目に遭って考えた、ビジネス継続性の重要さ
- 責められるべきはMSだけだろうか?
- セキュリティ技術者を「憧れの職業」にするには?
Copyright © ITmedia, Inc. All Rights Reserved.