神戸デジタル・ラボの「セルフチェックかんたん5」は試すな危険

 株式会社神戸デジタル・ラボが公表している「セルフチェックかんたん5」がWebアプリケーションセキュリティの一部専門家の間で話題になっている。

mi1kmanさん経由。 神戸デジタル・ラボさんの Webセキュリティ診断の販促ページ。 色々と言いたいことはありますが、一番は、「Webサイトセキュリティチェックリスト」の7ページ目:【中略】の部分ですかね。 手元の IE7/Firefox3 で試してみた限りでは、「http://int21h.jp/../」にアクセスした場合、ブラウザから出るリクエストの時点で「GET / HTTP/1.1」になっていました。(ブラウザが勝手に訂正してくれるので、GET /../ HTTP/1.1 のようなリクエストが送信されることは無さそう。) はたして“何らかのエラーメッセージ”が表示されることはあるのでしょうか…。(^-^;

http://yamagata.int21h.jp/d/?date=20081115#p01

yamagataさんのところから、「セルフチェック かんたん5 (プロアクティブ・ディフェンス) (yamagata.int21h.jp)」。
ふつうのブラウザから「../」入りのリクエストはできないはず、というお話ですね。
ブラウザを使わずに無理矢理送ることは可能ですが、IIS + ASP.NET の場合にはサーバ側で「../」を消化するような処理をされてしまうので、アプリケーションが「../」を含むURLを受け取ることはないようです。【後略】

http://bakera.jp/ebi/topic/3382

 確かに間抜けなチェックシートではあるが、益がない代わりに、特段の害もなく、一般の方が試しても問題になることはまずないだろう。
 ところが、同じチェックシートの『チェック3「内部データをのぞき見されているかもしれない」チェック』は、益は少しあるかもしれないが、それ以上に予期しないトラブル、具体的にはデータベースの破壊を招きかねないという点で、けっして「かんたん」というものではない。
 その検査パターンは以下のようになっている。

ログインのIDとパスワードの両方に以下のテキストを入力して下さい。
(シングルコーテーションもお忘れなく)


' or 1=1--

http://www.proactivedefense.jp/SelfCheck/img/selfcheck_5.pdf

確かにこれは典型的なSQLインジェクションのパターンになっている。以下のようなSQLがあったとする(言語はPerlを仮定)。


my $sql = "SELECT COUNT(*) FROM USERS WHERE ID='$id' AND PASSWORD='$pwd'";

ここで、$idと$pwdに「' or 1=1--」が代入されている場合、SQLは以下のようになる。


SELECT COUNT(*) FROM USERS WHERE ID='' or 1=1--' AND PASSWORD='' or 1=1--'

 標準SQLでは「--」以下はコメント(MySQLは「#」がコメント記号)だから、where句は常に真となり、パスワードを知らなくてもログインができてしまうというものだ。

 しかし、Webアプリケーションの検査には時として危険を伴う。そして、上記は典型的な「危険な検査パターン」でもあるのだ。
 具体例で説明しよう。認証の機能には、更新系のSQLが含まれる場合があり、その典型例は「最終ログイン日時の記録」だ。ユーザが最終ログイン日時を確認することにより、第三者が「なりすまし」でログインしていないか、確認できるようにしておくものだ。
 最終ログイン日時を記録するSQLは、例えば以下のようになっているだろう(Oracle Database 10g Express Editionにて確認)。


my $sql = "UPDATE LOGINLOG SET LASTLOGIN=SYSDATE WHERE ID='$id'";

 SYSDATEはシステム日付を取得する関数である。すなわち、ログイン成功したIDに対応するLASTLOGIN列をシステム日付でアップデートすることになる。
 ところが、ここで先の検査パターンが入力されると、上記のSQLは以下のようになる。


UPDATE LOGINLOG SET LASTLOGIN=SYSDATE WHERE ID='' or 1=1--'

 すなわち、「すべてのユーザ」に対して、最終ログイン日時を現在日時に更新してしまう。これでは、律儀なユーザは「誰かがなりすなして自分のIDでログインしている」と思い込むかもしれない。
 ここで挙げた例は、システムが全く使えなくなる性質のものではないが、それでも「簡単にチェックできるよ、試してみよう」というには、リスクの高いものだ。それに、「もっと酷いこと」になる可能性も十分にあるのだ。例えば、先のパターンでログイン後に、パスワード変更を試したとすると、全ユーザのパスワードが変更され、他のユーザがログインできなくなる可能性がある。
 パスワード変更のSQLは例えば、以下のようになっているだろう。


my $sql = "UPDATE USERS SET PASSWORD='$newpwd' WHERE ID='$id'";

 ところが、ここで先の検査パターンが入力されると、上記のSQLは以下のようになる(新パスワードは「system1」と仮定した)。


UPDATE USERS SET PASSWORD='system1' WHERE ID='' or 1=1--'

 このSQLが実行されると、全ユーザのパスワードが「system1」に変更され、すなわち全ユーザは自分の知っているパスワードでログインできなくなる。利用者は大混乱に陥り、Webサイトのヘルプデスクでは電話が鳴り止まなくなるだろう。
 この状況に対して、先のチェックシートには以下のような注意書きが添えられている。

重要:
本チェックは擬似攻撃の一種です。あなたの管理下のサイト、もしくはサイト管理者から許可を得られている場合にのみ実施してください。無断で第三者の管理するサイトにチェックを行った場合、不正アクセス防止法に抵触する可能性がありますので、実施の際はご注意ください。
このチェックにより発生した問題について神戸デジタル・ラボはいかなる責任も負いませんので、ご自身の責任の範疇で実施下さい。

http://www.proactivedefense.jp/SelfCheck/img/selfcheck_5.pdf

 「不正アクセス行為の禁止等に関する法律」は「不正アクセス禁止法」と略した方がよいとは思うが、それはともかく、確かに上記の検査パターンを「無断で第三者の管理するサイトにチェックを行った場合」、不正アクセスに該当する可能性が高い。しかし、それと同時に「検査が招く可能性のある悪影響」についても言及しておくべきであろう。「このチェックにより発生した問題について神戸デジタル・ラボはいかなる責任も負いませんので、ご自身の責任の範疇で実施下さい。 」とあるが、その直前には、不正アクセス禁止法のことしか書いていないので、一般のユーザは「自社のサイトでチェックする分には問題ないのだな」と思うだろう。それでいて、データベースが破壊されても「自己責任」と言い張るのは、いささか無責任ではないか。
 SQLインジェクションの検査は、専門家がやっても時としてデータベースを破壊しかねないものであるので、診断に先立って必ず免責事項を取り交わす。そのような危険を伴う診断行為を一般ユーザに試させるのであれば、まずは安全第一の検査パターンを紹介した上で、診断に伴う危険性を十分に告知することが検査会社としての責務であると考える。