2015年2月18日水曜日

ブラインドSQLインジェクション

Webシステムを攻撃する手法としてSQLインジェクションが有名です。 今回は実際に、SQLインジェクションによりパスワードを盗む方法を説明します。

ログインフォームから送信したIDとパスワードが、ソースコード内で以下のような式でクエリされるとします。 また有効なIDが1つ判明しているものとします。ユーザから送信されたIDとパスワードがDB上の値と一致していなければ、クエリの返り値は0件なのでログインすることは出来ません。

  select * from user where id='$id' AND pass='$pass'

  1. 必ずログインする
  2. パスワードに以下の文字列を入力します。

    ' OR 1 OR '
    これは以下のように展開され実行されます。
      select * from user where id='$id' AND pass='' OR 1 OR ''
    
    OR 1が挿入されることにより無条件でuserがselectされてしまいます。 クエリ結果の最初のユーザをログインユーザとする、と処理されるシステムの場合、この方法によりパスワードを知らなくても必ずログインすることができます。

  3. パスワードを見つける
  4. 上記の方法によりログインそのものは成功しますが、パスワードはまだ判明していません。
    挿入する文字列を工夫することで更にパスワードまで判明させることが出来ます。

    ' OR 1 OR '
    としていたのを
    ' OR pass like '%' OR '
    と書き換えます。 これは以下のように展開されます。
      select * from user where id='$id' AND pass='' OR pass like '%' OR ''  
    
    %は0文字以上の任意の文字列にヒットします。 この状態でもやはりログインに成功します。 次は以下の文字列をパスワードとして送信します。
    ' OR pass like 'a%' OR '
    これはpassの最初の1文字目が'a'であるもののみにヒットします。
    この結果はログイン成功 / ログイン失敗に分かれます。
    もし指定したIDのuserのpassの1文字目がaであった場合は、ログインに成功します。
    もし指定したIDのuserのpassの1文字目がaでなかった場合は、ログインに失敗します。
    これをa ~ Z, 0 ~ 9の全ての文字に対して行うことで確実にpassの最初の1文字を特定することが出来ます。
    1文字目を特定することが出来れば同じ原理で2文字目以降も特定可能です。
    もし全ての文字に対してログインが失敗した場合、次の文字はありません。

    このようにして、パスワードを盗むことができます。

0 件のコメント :

コメントを投稿