skipfishをためす

Googleから新しい検査ツールが出たとのことで、中身を見てみました。

Google Code Archive - Long-term storage for Google Code Project Hosting.

ツールの作者はRatproxyと同じくMichał Zalewski氏ですが、今回のツールはRatproxyとは違って"Active"な検査ツールです。

最新版のVersion 1.29ベータをダウンロードして使ってみました。

シグネチャと検査結果

こちらのページを参考にしてダウンロード・インストールしました。

skipfishインストールメモ | 俺のメモ

プログラムはC言語で書かれており、ヘッダファイルを含めて10KL程度の規模です。

インストール後にツールを起動すると、開始点として指定したページからリンクをたどって自動的に検査してくれます。検査が終わるとHTMLのレポートを出力してくれます。

私が検査対象としたアプリは、Oracleデータベースを操作する20個くらいのServletで、そのすべてにSQL Injection脆弱性があります。

検査は起動後4〜5分程で終了しました。この間にツールが送信したHTTPリクエストは10万を超えており、たかだか20個ほどのServletに対する検査としては多すぎます。実は、skipfishにはWebサーバのディレクトリやファイルを辞書探索して検査対象を見つけ出す機能があり、リクエストの大半はそこに費やされていました。

SQL Injectionについて

SQL Injectionについては、20個ほどのアプリのうちツールで検出できたのは2個だけでした。この2個はいずれもSELECT文のWHERE句の数値リテラルにインジェクションするタイプのものです。この2個のうち1つはBlindタイプ(=SQLエラーメッセージがHTMLに出ないもの)です。

数値リテラル以外はどうかというと、文字列リテラルや「ORDER BY」等にインジェクションするものは、SQLエラーがHTMLに出力されるものを含めて検出されませんでした。

理由を探るべくログやソースコードを見てみたところ、SQLインジェクションはBlind的な判定しか行っておらず、さらに文字列リテラルの検査としては以下の3つのパターンしかないことが判りました。

0:  \'\"
1:  '"
2:  \\'\\"

判定は「0の応答≠1の応答 かつ 0の応答≠2の応答」の場合にPositiveとしています。文字列リテラルエスケープに「\」が使用可能なデータベース(基本的にMySQLと一部のPostgres)を念頭にシグネチャが作られていることが判ります。

なので、それ以外のデータベースの文字列リテラルへのインジェクションは検出できません。また、MySQL用の検査パターンとしても少々物足りない感じです。

それ以外の検査パターン

検査パターンは「crawler.c」ファイルに書かれています。このファイルをみると判りますが、Blind方式で様々な脆弱性を検出するように作られています。

そのうち、わかりやすいものをいくつか挙げます。

OSコマンドインジェクション

バッククォートを使ってコマンドを動かし、Blind的な判定を行います。

0:  `true`
1:  `false`
2:  `uname`

3:  "`true`"
4:  "`false`"
5:  "`uname`"

6:  '`true`'
7:  '`false`'
8:  '`uname`'

「0の応答≒1の応答 かつ 0の応答≠2の応答」の場合にPositiveと判定しています。3〜5、6〜8も同様の判定を行っています。

明示的にShellをたたいて、その結果をHTMLに出力しているようなアプリについては、このパターンで検出できそうです。しかし、そうでないケース(=このアプローチでは検出できないケース)はかなりあると思います。

また、3〜5のパターンは「"」の内側にインジェクションするケースを想定しているのだと思いますが、その場合には0〜2で検出できるので不要な気がします。

OGNL Statement Excecution

これは、おそらくStruts2XWork)のOGNL文実行の脆弱性http://jira.opensymphony.com/browse/XW-641[WW-2030] User input is evaluated as an OGNL expression - ASF JIRA、他)を意識したものだと思います。

おおざっぱに言うと、skipfishは以下のようにパラメータ名・値を変化させて、「0の応答≒1の応答」の場合にPositiveと判定しています。

0:  foobar=123
1:  [0]['foobar']=123

しかし、これだけだとOGNL likeなパラメータハンドリングがされていることはわかっても、本当に脆弱性があるかどうかまではわかりません。

ちなみに、struts2脆弱性は、パラメータ名の処理だけではなく値の処理の方にもありました。そちら(値の処理の脆弱性)を利用する方が確実にコマンドの実行を判定できるので、私の自作ツールではそのようなシグネチャを使っています。

おわりに

今回は網羅的に調べたわけではありませんが、まだ試作段階のツールといった感じを受けました。

しかし、セールスポイントである"高速性"については宣伝通りです。localhostの80ポートに対する検査とはいえ、4〜5分のうちに10万を超えるリクエストを発行する能力はすごいです。その能力は、上述したサーバ上のディレクトリやファイルを辞書探索する機能で活かされています。

また、ドキュメント(Google Code Archive - Long-term storage for Google Code Project Hosting.)をみると、Ratproxyと同じくXSSJavaScript/JSON関係は色々と検査してくれるようです。今回はその辺は全く見てませんが、突っ込んでみてみると面白いかもしれません。