ikepyonの日記

2004-12-01Webアプリケーション検査

[]

Webアプリケーションセキュリティチェックの面倒なところは、あまりにもテストケースが多いことだったりする(単に上記のセキュリティチェックリストにある様なパターンを投げつけて結果を保存するツールは作ったんだけど、チェックするパターンがあまりにも多すぎてチェックに挫折してたりする)。で、AppScan等のツールを使ってテストすることになるのだけどここにも問題があったりする。

それが、脆弱性がある場合の応答が一意でないのでシステム的に決めてしまうのが難しいということであったり、もっともXSSの場合はHTTP応答だけを見て正規表現でチェックすればよいので楽なんだけど。コマンドインジェクションやSQLインジェクションの場合はHTTPの応答だけでは不可能なのでScaner側でサービスポートを待ち受けて攻撃が有効だったらアクセスに来る様なことをしてやればいいかなぁと思っていたら、すでに最新のAppScan(日本語版じゃないよ)ではそういう仕様っぽいし・・・やられたorz

http://www.watchfire.com/news/releases/10-12-04.aspx

[]

Webアプリケーションセキュリティチェックにおいて判断が難しいのは、SQLインジェクションであったりする。実際には、わざとSQLエラーを発生させるパターン(「'」だけとか「"」だけとかSQL構文的にエラーとなるもの)を入れてみて、エラーが発生することを期待する。

応答として、「ODBC Error」とか「SQL Error」、「ORA-xxx」等が表示されたらSQLインジェクションが可能であることは確実だと思われる。というかDB呼び出しでエラーが発生しないという思い込みで作られたもののようなので、問題外だったりする。こんなつくりにしてる人は即効エラー処理ぐらい入れること。

問題はこれ以外のエラーメッセージであった場合である。

DBにアクセスした場合考えられるエラーとしては、「RDBMSからの応答がない、RDBMSシステムエラーをはいた」か、「SQLにエラーがある」場合が考えられる。

ところが、脆弱性のあるWebアプリケーションでエラー処理を行っている場合、以下のパターンのエラーメッセージが可能性として考えられる。

  1. データベースアクセスできませんでした。」系
  2. 「現在処理が立て込んでいます。再度アクセスしなおしてください。」系
  3. 「エラーが発生しました。」系
  4. 「不正な文字が含まれています。」系

このうちもっとしっかりエラー処理をしていそうなのは4である。各々の場合にどういった可能性があるか考えてみる。

これは一応DBのエラーが発生したら、内容を考えずにエラーとしていると考えられる。

このケースの場合、開発者は「DBのエラーなんだから、SQL文は正しいし、きっとRDBMSからの応答がないんだろう。」と思っていると考えられる。しかし、このエラーがでると「ODBCエラー」やら「SQL Error」やらとほぼ同じことであることに開発者は気がついていないらしい。しかも、バックエンドにDBがあることが分かるので(わざわざデータベースアクセスできないと書いてあるし)、SQLインジェクションの攻撃を受けやすくなる。

これをツールで検出しようとすると文字列が固定ではないので機械的に引っかかることが出来ない。

  • 2.「現在処理が立て込んでいます。再度アクセスしなおしてください。」系

このケースでは、開発者は「RDBMSからエラーが帰ってきたら、ありうるのはレスポンスが遅い場合だけだろう。だから、「混んでいます」でいいや」と考えたのだろう。

これもまた、文字列が固定でないので機械的に引っ掛けることができない。

  • 3.「エラーが発生しました。」系

このケースでは開発者は「エラーの詳細を出すのはセキュリティ上よくないから、出さない様にしよう」と考えたのだろう。

このケースではきっちり文字列のチェックを行っている可能性もあるが、DBのエラーを十羽一絡げに纏め上げている可能性もある(どちらかというとその可能性のほうが高いだろう)。

これもまた、文字列が固定でないので機械的に引っ掛けることができない。

  • 4.「不正な文字が含まれています。」系

このケースがもっともセキュリティ上問題がある可能性が低いと考えられる。だが、可能性として次のことが考えられる。開発者が文字列チェックを忘れていて、「SQLエラーが発生するということは、何かSQLとして問題のある文字が入力されたのだろう。だから、不正な文字列が含まれているとかんがえればいいんじゃないの」と考えている可能性が存在する。

これの場合に脆弱性を検出するのは、大変になりそうである。


各文字列を意味を解釈して判断するのは人には出来ても機械には無理なので機械的に判断できる方法を考えてみる。

方法としては入力文字チェックがなされていればエラーとなるが(つまり、「'」、「"」を含み)、SQL構文的には問題がないようなデータを入力して反応を見てみれば良い(具体的なデータは自分で考えてね、某組織に不正アクセス禁止法幇助で捕まりたくないので:P)。

SQL構文的にエラーとなるデータを渡したときにWebアプリケーションでエラーと判定し、SQL構文的にエラーとならないデータを渡したときWebアプリケーションがエラーとならなかった場合、このWebアプリケーションにはSQLインジェクションの問題があると考えられる。

一方、SQL構文としてエラーのあるなしにかかわらずWebアプリケーションでエラーとなった(両方の場合に正常でも一緒)場合、このWebアプリケーションにはSQLインジェクションの問題はないと考えられる。

実はこの方法だと誤検知する場合がある。どういった場合かというと、SQL構文的にエラーとなる文字列が既にデータとして格納されている場合である。

入力したデータが検索キーだったりするとSQLの結果が表示され、アウトプットがSQL構文的にエラーとならない文字列の結果と異なってしまうのである。従って、脆弱性はないのに脆弱性があると認識されることが考えられる。

まあ、この手法を使って検査する場合そんな変なデータが格納されていなければ問題がないので大きな問題とはならないだろうけど(最も攻撃しようとしてるやつが間違って脆弱性があると認識しても知ったことか)。

ということで、問題なさげ。

[]

SQLインジェクションに引き続き、これも検出するのが難しかったりする。

まあ、方法としてはこんな感じでどうだろう?

実際に存在するファイルへの相対パス表示をデータとして入力する。ディレクトリトラバーサルが有効であれば、ファイルは存在するのだから、「ファイルが存在しない」というエラーはでないはず。逆に無効であれば、「ファイルが存在しない」というエラーが発生するはずである。

当然文字列は固定でないので、これを機械的に見つけ出すのは不可能である。

そこで、SQLインジェクションと同じように考える。

今度は実際に存在しないようなディレクトリ配下にあるファイルへの相対パス表示をデータとして入力する。ディレクトリトラバーサルが有効、無効にかかわらずこの場合は「ファイルが存在しない」というエラーになるはずである。

この二つの結果を比較して同じであれば、脆弱性がなさそうであるといえるし、異なれば脆弱性がありそうといえそうである。

さて、本当にこれでうまくいくのか?

実はこれではうまくいかないケースがある。Webアプリケーション内で入力ファイルファイルフォーマットチェックを行っていて、かつ「ファイルが存在しない」というエラーと同じエラーメッセージであった場合はこの方法では判断できない。

でも、この場合ってブラックボックステストではどうやっても分からないと思う。

おっよく考えたらこれって脆弱性ないことにならんか?ただ、チェックする側からすると問題があるかないかはわからないという結果しかえられんか(実在するファイルのつもりが実際には存在しない可能性があるから、まあ適切に選べばたぶんこんなことは起こらないだろうけど)。

[]

  1. 権限の異なるアカウントA,Bを2つ用意する。
  2. アカウントAでログインし、そこで使用されているHiddenフィールドCookieの値を全て保存する。
  3. アカウントBでログインし、先ほど記憶していたHiddenフィールドCookieアカウントBでログインした後のHiddenフィールドCookieを比較し、同じ名前かつ値がことなるものを抽出する(これをCとする)。
  4. アカウントBでログインした状態で、Cの1つの値をアカウントAでログインしたときの値に書き換えてアカウントAで特徴的な操作(つまりアカウントAでは出来てアカウントBでは出来ないこと)をおこなう。

これが可能であれば権限上昇が可能であるといえる。

実際に検出するには4で実行した結果とアカウントAで実行した結果を比較して同じだったら権限上昇可能ということになる。