ikepyonのだめ人間日記

セキュリティに関することを書いていく予定。

えーと、ツールの仕様固め代わりにメモ。悪用厳禁だったりする。

SQLインジェクション

Webアプリケーションのセキュリティチェックにおいて判断が難しいのは、SQLインジェクションであったりする。実際には、わざとSQLエラーを発生させるパターン(「'」だけとか「"」だけとかSQL構文的にエラーとなるもの)を入れてみて、エラーが発生することを期待する。
応答として、「ODBC Error」とか「SQL Error」、「ORA-xxx」等が表示されたらSQLインジェクションが可能であることは確実だと思われる。というかDB呼び出しでエラーが発生しないという思い込みで作られたもののようなので、問題外だったりする。こんなつくりにしてる人は即効エラー処理ぐらい入れること。

問題はこれ以外のエラーメッセージであった場合である。
DBにアクセスした場合考えられるエラーとしては、「RDBMSからの応答がない、RDBMSがシステムエラーをはいた」か、「SQLにエラーがある」場合が考えられる。
ところが、脆弱性のあるWebアプリケーションでエラー処理を行っている場合、以下のパターンのエラーメッセージが可能性として考えられる。

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

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

  • 1.「データベースにアクセスできませんでした。」系

これは一応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インジェクションの問題はないと考えられる。

というようなロジックであれば、検出が出来そう。うまくやれば同様のことがコマンドインジェクションでも判断できそう。