pg_sleepを使った検査

徳丸さんの日記(pg_sleepをSQLインジェクション検査に応用する - ockeghem's blog)を読みました。

こういう検査のマニアックな話は大好きです。

このあたりのシグネチャは、私も自作ツール(参考)の検討をしていた際に相当いろいろ悩んで調べましたので、今回はUPDATE文のSET句などにも適用できるような改善の提案をしたいと思います(おろらく既に徳丸さんの頭にあるものだとは思いますが)。

徳丸さんの日記の検査パターンは、以下の値を挿入するものでした。

' and cast( (select pg_sleep(3)) as varchar) = '

これを少し変えて、以下のようにします。

<文字列型>
【元の値】'||(select pg_sleep(3))||'

数値型であれば、以下のようにします。

<数値型>
【元の値】-cast(chr(48)||(select pg_sleep(3)) as int)

上の二つはいずれも「AND」などを使っていないため、SELECT以外の文(UPDATEのSET句やINSERTのVALUES句)や、IN ('foo','bar')のような箇所にインジェクションするケースにも適用可能です。

なお、SQLのブロックコマンドを使うトリッキーな方法を用いると、いっぺんに文字列/数値型の両方に対応した検査ができます。

<文字列/数値型 両方対応>
【元の値】/*'||(select pg_sleep(3))||'*/-cast(chr(48)||(select pg_sleep(3)) as int)

ちょっと長いので、アプリの長さチェックなどに引っかかる可能性が増えるのが難点です。

****

しかしいろいろ考えた挙句、自作ツールにはこれらのシグネチャは組み込みませんでした。その理由はいくつかありますが、一番大きい理由は「postgres(しかもv8.2以上)を使っているサイトが(相対的に)少ない」ということです*1

見方を変えると、postgres8.2以上を使っていることがはじめから判っているサイトを検査する状況においては、pg_sleepを使った検査手法も有効なのだろうと思います。

余談ですが、pg_sleepはワイルドな攻撃では実際に使われているようです。google検索の結果には、pg_sleepを使った攻撃の痕跡と思われる不自然なURLが残っています。

http://www.google.co.jp/search?q=inurl%3Apg_sleep&lr=

以前google検索した時には、もう少し多くの攻撃の痕跡が見つかったような記憶があります。調べてませんが、何かの攻撃ツール(もしくは検査ツール)がpg_sleepを使っているのかもしれません。

*1:自作ツールにはOracle用のTime delay系のシグネチャだけを入れました。