これらのエントリに異論があるわけでありません。メールアドレスに関するルールというとRFC5322などがあるものの、現実の運用では簡易的な仕様を用いている場合が大半である…という事情は、私も以前ブログに書きました。、
本稿では、「空前のメールアドレスのルールブーム(?)」に便乗する形で、RFC5322に準拠したメールアドレスで、XSSやSQLインジェクションの攻撃ができることを紹介します。と言っても、SQLインジェクションについては、過去に書きましたので、本稿では、RFC5322バリッドなメールアドレスでSQLインジェクションとXSSの両方ができるメールアドレスを紹介します。
まず、攻撃対象として、以下のログインスクリプトを用います。メールアドレスはfilter_varを用いてメールアドレスとしての妥当性を確認し、パスワードは英数字のみであることをctype_alnumを用いて確認しています。
実行例を示します。まずは、ログイン成功の場合です。最下行にログインユーザ名が表示されますが、ここにXSS脆弱性があります。<?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攻撃に必要な記号文字 < や > はダブルクォートで囲まないとメールアドレスのローカルパート(@の左側)では使えないため、ダブルクォートで囲ったメールアドレスにします。以下にそのような例を示します。
ここで、/**/は空のコメントですが、filter_varによるメールアドレスチェックでは(quoted-stringでも)空白がエラーになった(*1)ので、空白の代わりに使用しています。"><script>alert('or/**/1=1#')</script>"@example.jp
このメールアドレスを先のログインスクリプトに指定すると、以下の画面になります。
ちゃんと(?)XSSが発動していますね。OKボタンをクリックすると続いて下記の画面になります。
SQLインジェクション攻撃により、IDが存在しないのにログインに成功しています。
なお、このメールアドレスはRFC準拠なので、ThunderbirdとGmailでは、このメールアドレス(ドメイン名は変えました)に送信可能であることを確認しています。Becky!での送信は括弧のせいでエラーになるようです。
ということで、RFC5322バリッドで、SQLインジェクションもXSSもできるメールアドレスを示しました。
ただし、このメールアドレスは中々に危険です。その理由については私の過去のエントリを御覧ください。このため、この種のメールアドレスを公開Webサイト等で試すことは避けてくださいますようにお願い致します。
*1 phpallで確認したところ、PHP5.3.2までは空白入りのメールアドレスがValidと判定されていましたが、PHP5.3.3以降ではエラーになるようです。