2013年11月29日金曜日

XSSとSQLインジェクションの両方が可能なRFC5322適合のメールアドレス

メールアドレスの「ルール」に関する話題が盛り上がっていますね。
これらのエントリに異論があるわけでありません。メールアドレスに関するルールというとRFC5322などがあるものの、現実の運用では簡易的な仕様を用いている場合が大半である…という事情は、私も以前ブログに書きました。、
本稿では、「空前のメールアドレスのルールブーム(?)」に便乗する形で、RFC5322に準拠したメールアドレスで、XSSやSQLインジェクションの攻撃ができることを紹介します。と言っても、SQLインジェクションについては、過去に書きましたので、本稿では、RFC5322バリッドなメールアドレスでSQLインジェクションとXSSの両方ができるメールアドレスを紹介します。
まず、攻撃対象として、以下のログインスクリプトを用います。メールアドレスはfilter_varを用いてメールアドレスとしての妥当性を確認し、パスワードは英数字のみであることをctype_alnumを用いて確認しています。
<?php
  define('USERNAME', 'xxxxx');
  define('PASSWORD', 'xxxxx');

  $err = $id = $pwd = '';
  // ユーザID(メールアドレス)のバリデーション
  if (isset($_GET['id']) && filter_var($_GET['id'], FILTER_VALIDATE_EMAIL)) {
     $id = $_GET['id'];   // ユーザID
  } else {
     $err .= 'ユーザIDはメールアドレスを指定してください<br>';
  }
  // パスワード(英数字)のバリデーション
  if (isset($_GET['pwd']) && ctype_alnum($_GET['pwd'])) {
    $pwd = $_GET['pwd']; // パスワード
  } else {
     $err .= 'パスワードは英数字を指定してください<br>';
  }
  if ($err !== '') {
    die($err); // バリデーションエラーの場合はエラーメッセージを表示して終了
  }
  // データベースに接続
  $dbh = new PDO('mysql:dbname=test;host=localhost;charset=utf8', USERNAME, PASSWORD);
  // SQLの組み立て
  $sql = "SELECT * FROM users WHERE id ='$id' AND pwd = '$pwd'";
  $stmt = $dbh->query($sql);  // クエリー実行
?><html>
<body><?php
  echo 'sql= ' . htmlspecialchars($sql, ENT_NOQUOTES, 'UTF-8') . '<br>';
  if ($stmt->rowCount() > 0) { // SELECTした行が存在する場合ログイン成功
    echo "ログイン成功です(id:$id)";
  } else {
    echo 'ログイン失敗です';
  }
  $dbh = 0;
?></body>
</html>
実行例を示します。まずは、ログイン成功の場合です。最下行にログインユーザ名が表示されますが、ここにXSS脆弱性があります。


次に、ログイン失敗の場合です。


これに対する攻撃メールアドレスですが、XSS攻撃に必要な記号文字 < や > はダブルクォートで囲まないとメールアドレスのローカルパート(@の左側)では使えないため、ダブルクォートで囲ったメールアドレスにします。以下にそのような例を示します。
"><script>alert('or/**/1=1#')</script>"@example.jp
ここで、/**/は空のコメントですが、filter_varによるメールアドレスチェックでは(quoted-stringでも)空白がエラーになった(*1)ので、空白の代わりに使用しています。
このメールアドレスを先のログインスクリプトに指定すると、以下の画面になります。


ちゃんと(?)XSSが発動していますね。OKボタンをクリックすると続いて下記の画面になります。


SQLインジェクション攻撃により、IDが存在しないのにログインに成功しています。

なお、このメールアドレスはRFC準拠なので、ThunderbirdとGmailでは、このメールアドレス(ドメイン名は変えました)に送信可能であることを確認しています。Becky!での送信は括弧のせいでエラーになるようです。


ということで、RFC5322バリッドで、SQLインジェクションもXSSもできるメールアドレスを示しました。

ただし、このメールアドレスは中々に危険です。その理由については私の過去のエントリを御覧ください。このため、この種のメールアドレスを公開Webサイト等で試すことは避けてくださいますようにお願い致します。

*1 phpallで確認したところ、PHP5.3.2までは空白入りのメールアドレスがValidと判定されていましたが、PHP5.3.3以降ではエラーになるようです。

0 件のコメント:

コメントを投稿

フォロワー