星野君 「へぇ〜……」
星野君は、「なるほど」と感心した。しかし、少し考えた後で「これを悪用できるのだろうか?」という疑問がわいた。
星野君 「けど、結局のところ、メールアドレスが判別できるっていうだけの被害じゃないですか?条件文を追加したら登録情報が全件見えちゃった、とかいうわけでもないですし……」
赤坂さん 「えー。SQLインジェクションの被害って、そんな単純なのじゃないよ。この状態で、データベースの中の情報抜けちゃうって」
星野君 「え?マジっすか??」
赤坂さん 「例えば最初に、テーブル名の1文字目を判別する条件式を付けて……」
前述のように、追加するSQL文が「' and '1' = '1」などのような単純なものの場合は特に問題にならない。しかし、この条件文にはサブクエリのような複雑なものを入れることが可能なのである(DBMSの種類、バージョンによってはできないものもある)。
例えば、PostgreSQLの場合、以下のようなサブクエリを条件文として追加することで、テーブル名の1文字目を取得することができるのである。
SELECT login_id FROM user_table WHERE mail = 'hoshino@example.co.jp' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables whereTABLENAME !~ '^(pg_|sql_)'),1,1))) >110 - ' ; |
この条件式では、サブクエリとしてSELECT文を挿入し、テーブル名を取得している。次にsubstring関数によって、テーブル名の1文字目を取得する。その取得した文字を判別しやすいようにlower関数で小文字に変換した後、ascii関数によって数字に変換し、数値「110」との比較を行っている。
ここで利用している比較対象の数字「110」は、asciiコードで小文字の「n」を示している。仮にテーブル名がアルファベットのみの場合、「hoshino@example.co.jp」が登録されている状態でこの条件式を挿入し、そのまま処理が進めば「偽」、つまりテーブル名の1文字目はa〜mの範囲ということが分かる。逆に、「メールアドレスが重複しています」というエラーメッセージが表示されれば「真」、つまりテーブル名の1文字目はn〜z範囲、というように絞り込んでいくことが可能となる。
これを繰り返し行うことで、テーブル名の全体を取得し、さらにはサブクエリを変化させることで深く掘り下げていくことが可能になる。この手法はブラインドSQLインジェクション(Blind SQL Injection)と呼ばれる。
【参考リンク】
Blind SQL Injection white paper
http://www.spidynamics.com/whitepapers/Blind_SQLInjection.pdf
対策は、星野君が自社のWeb管理画面で見つけたSQLインジェクションと同様に、「'」(シングルクォート)や「\」(バックスラッシュ)などの特殊文字記号をエスケープすればよい。しかし、外から見て明らかにおかしな挙動をしていなくても成立する攻撃であるため、テストの際に見落としてしまう可能性が高いので注意が必要となる。
星野君 「なるほど……。かなり深いですね。これならデータベースの中の情報が全部取れちゃいそうですね」
赤坂さん 「でしょー。こういうのって致命的な脆弱性だから、見逃したら大変」
星野君 「でも、実際にやろうと思ったら地道すぎてあんまりデータ取れなさそうですねー」
赤坂さん 「そんなことないよ。ブラインドSQLインジェクションに特化してこの絞り込みの作業を自動化したツールとかあるよ」
星野君 「え??そんな攻撃するためのツールなんてあるんですか??」
赤坂さん 「アングラっぽい感じのでいくつかあるみたいだよ。怪しげだから使ったことないけどー」
星野君 「(そんなツールまで存在するのか……。もっと勉強しないとダメだなぁ……)」
星野君は、今回検査をさせてもらった範囲以外でもどんな脆弱性があるのか気になったが、赤坂さんは用事があるため帰るとのことで、詳しく教えてもらうのは次の日となった。
簡単に教えてもらったところでは、ほかにはSQLインジェクションのような致命的な脆弱性はなかったようだ。赤坂さんの見解は、このメールアドレスの重複チェックの部分だけ後付けで別の人が作ったのではないかということらしい。
こういったメールアドレスの重複チェックや郵便番号検索など、もともとの機能としては必須ではないような機能の場合、後からほかの人が追加するということがあるようで、安易な機能追加によりこういった脆弱性が生まれやすいという。
山下君 「星野〜。そろそろ帰るけど一緒に帰るー?」
星野君 「あー。あと5分待ってー」
山下君 「あいよ。お腹すいたからご飯でも食べて帰ろ」
星野君 「うん」
星野君は、やりかけの作業を片付け、ご飯を食べるために山下君と一緒にファミレスへ向かった。
山下君 「仕事どう?異動になってから」
星野君 「んー。基本的にやること一緒で場所が変わっただけだからなぁ。異動したから変わったことってあんまりないね。けど、環境としては前よりいいかな」
山下君 「そっか。楽しくやれてるみたいで何よりだね」
星野君 「うん。けど今日、まだまだ勉強しなきゃいけないことたくさんあるなーって感じたよ」
山下君 「今日何か新しいことやったのー?」
星野君 「お客さんのWebアプリケーションを検査するっていうのをちょこっとやらせてもらったんだけどね。これがまた難しくって」
山下君 「へぇ〜。自分とこのWeb管理だけじゃなくて、お客さんとこもちょっと見てるんだ」
星野君 「うん。けど、一緒にやってた赤坂さんが見つけてた脆弱性見逃しちゃったし。いままでも結局まこと先輩に教えてもらいながらやってた感じだしなぁ」
山下君 「うん?あれ?今回は??」
星野君 「え?今回は特にまこと先輩にはメールしてないなぁ」
山下君 「メール?あ、もしかして、まこと先輩が誰か分かってなかったりする?」
星野君 「そっか、同じフロアだから直接聞きにいけばいいのかー」
山下君 「あ、なんか面白そうだから誰がまこと先輩か教えないでおこっと」
星野君 「えー。教えてよー」
次回予告:
Webアプリケーションの検査については、まだまだ勉強が必要な星野君。まこと先輩との直接対面はうまく果たせるのだろうか。
Check!
簡単に目に見えるものだけが脆弱性ではない
ブラインドSQLインジェクションのように、Webアプリケーションのちょっとした挙動の違いからデータベースの情報が漏えいするといった思いもよらない結果になることがある
Webアプリケーションを安全にするには、内部でどのようなことが起きているかを把握しながら検査を行うことが必要だ
Check!
安易な機能追加を行うと脆弱性が発生してしまう
「簡単に実装できるから」とセキュリティに詳しくない人が機能を追加し、脆弱性が発生してしまうことが少なくない。せっかく安全なWebアプリケーションを作っても、1つの脆弱性で致命的な被害につながってしまう可能性がある。機能を追加するときにも慎重になろう
杉山 俊春(すぎやま としはる)
三井物産セキュアディレクション株式会社
テクニカルサービス事業部検査グループ
コンサルタント
セキュリティコンサルタントとして、主にWebアプリケーションのセキュリティ検査などに従事している。大手就職活動支援サイト、ショッピングサイトなどの検査実績を持つ。
Copyright © ITmedia, Inc. All Rights Reserved.