目的
実装したWAFが正しく機能しているのか「SQLインジェクション(SQLi)」と「クロスサイトスクリプティング(XSS)」で攻撃してみて、防御できること検証する手順。を記録するもの。
内容
- クラウドサービス型のWAF: Web Application Firewall
- WAFはアプリケーションの脆弱性を悪用した攻撃を、ネットワーク機器レベルで防御してくれる。
- 正しく防御してくれるか、わざと脆弱性のあるアプリに攻撃してみる。
- 攻撃は、SQLインジェクションとクロスサイトスクリプティングの2つ。
手順の概要
わざと脆弱性のあるWEBサーバーを作って、自分のPCから攻撃する。「WAFが無い場合」と「WAFが有る場合」とで比べる。
今回のシステム構成(必要なモノ)
- 今回メインで試すのは、クラウドWAFとして「IBM Cloud Internet Services(通称: CIS)」を使う。
- ドメインは、予算の都合上で「AWS Route53」のドメイン名とDNS機能を使う。
- 仮想サーバーは、IBM WAFでマルチクラウドを対象に防御できることを検証するので「Azure VM」を使う。
※おおー、これってマッシュアップっていうんじゃなくて?
WEBサーバーの準備
WEBフォームにIDとパスワードを入力すると、個人情報データベースから自分だけのメールアドレスが検索されるプログラムを作る。
サンプルスクリプト等はGithubに保存してあります。
その1.個人情報データベースのテーブルをmySQLで作成。
▼こんな感じ。データベース名は「system」、テーブル名は「users」。
mysql> select * from users;
+------+---------+--------------------+
| uid | passwd | email |
+------+---------+--------------------+
| 1 | pass | hoge1@asahi.jp |
| 2 | parking | hoge2@asahi.jp |
| 3 | signal | hoge3@asahi.jp |
| 4 | driver | hoge4@asahi.jp |
| 5 | hello! | hoge5@asahi.jp |
| 6 | cloret | hoge6@asahi.jp |
| 9 | loveit | hoge9@asahi.jp |
| 10 | sqlsql | ダメじゃん。 |
| 11 | dbdbdb | Oops!! NoGood!! |
+------+---------+--------------------+
9 rows in set (0.00 sec)
その2.WEBフォームをHTMLで書く。
▼こんな感じ。ファイル名は「sqltest.html」。
<html>
<meta charset="UTF-8">
<head>
<title>SQL injection test</title>
</head>
<body>
<h1>SQL injection test</h1>
<form action="db.php" method="post">
<table>
<tr>
<td>User ID</td>
<td><input type="text" name="uid"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="text" name="password"></td>
</tr>
</table>
<input type="submit" value="Submit">
</form>
<br />
</body>
</html>
その3.データベースを検索するSQLをphpで書く。
▼こんな感じ。DBパスワードは適宜置き換えて。ファイル名は「db.php」。
<html>
<meta charset="UTF-8">
<head>
<title>Result of MySQL query</title>
</head>
<body>
<?php
$conn = mysql_connect('localhost', 'root', 'Sqlpassw0rd!!');
$db = mysql_select_db('system', $conn);
$uid = $_POST['uid'];
$pass = $_POST['password'];
print "debug: uid='$uid' password='$pass'";
$result = mysql_query("SELECT email FROM users where uid='$uid' AND passwd='$pass'");
if (mysql_num_rows($result) == 0) {
echo "<h2>Error either user ID or password, try again.</h2>";
exit;
}
if (mysql_num_rows($result) == 1) {
echo "<h2>Good! it was Right query.</h2>";
}
if (mysql_num_rows($result) >= 2) {
echo "<h2><font color='red'>!!! SQL injection success !!!</font></h2>";
}
while ($row = mysql_fetch_assoc($result)) {
print('Secret email is '.$row['email']);
print('.<br>');
}
mysql_close($conn);
?>
<a href="sqltest.html">Back to previous input box.</a>
</body>
</html>
その4.何を入力してもそのまま値を表示するphpを書く。
▼こんな感じ。ファイル名は「testxss.php」。
<html>
<body>
<form action="" method="post" accept-charset="utf-8">
名前: <input type="text" name="name" value=""/>
年齢: <input type="text" name="age" value=""/>
<input type="submit" value="submit"/>
</form>
<br />
こんにちは、<?php echo $_POST['name']; ?>さん。
あなたは、<?php echo (int)$_POST['age']; ?> 歳です。
</body>
</html>
WEBサーバーの脆弱性を悪用して攻撃してみる
その1.SQLインジェクション攻撃
まずは正しい動作から。
攻撃した場合
パスワード入力欄に「'OR '2' = '2」をインプットするとSELECT文「SELECT email FROM users where uid='$uid' AND passwd='$pass'」のpasswd部分が「誤ったパスワード、もしくは、'2' = '2'」となり常に正しいパスワードだと判断されてデータを取得できちゃう。
WAFが有る場合
先ほどと同じパスワード「'OR '2' = '2」をインプットしてSubmitを押す。ちなみに「' OR 'ABC' = 'ABC」等でもテストできる。WAFがWEBサーバーへのアクセスをブロックした。
その2.クロスサイトスクリプティング[XSS]
まずは正しい動作から。
攻撃した場合(Chromeブラウザ)
名前の入力欄にポップアップしちゃうスクリプト「<script>alert('攻撃しちゃうぞ');</script>」をインプットする。ところがchromeブラウザが脅威を検知してしまった。この検証は失敗。
攻撃した場合(IEブラウザ)
今度はIEでスクリプト「<script>alert('攻撃しちゃうぞ');</script>」をインプットする。よし、正しく攻撃できた。今回はポップアップだけだが、ここに悪意あるスクリプトを埋め込むと危険。
WAFが有る場合
先ほどと同じスクリプトをインプットすると、WAFが注意画面を表示した。「□私はロボットではありません」にチェックをすると次の画面に進んだ。注意喚起だけなのかな。イベントログにはきちんと記録されていました、「チャレンジ」として。
[後日アップデート]XSSもブロックされるようになりました。イベントログにも「ブロック」として記録されるようになりました。
▽イベントログの一部
まとめ
WEBサイトをインターネットの脅威から防御するための手段としてWAFを実装する。WAFを初期設定して、きちんとWAF経由で防御できているかを検証するための手順を確認できた。
参考
▽IBM Cloud Internet Services (CIS)を使ってみた(オーダー・初期設定)
<>