クラウドWAFで、WEBアプリを防御できているのか？ を検査する

## 目的
実装したWAFが正しく機能しているのか「SQLインジェクション(SQLi)」と「クロスサイトスクリプティング(XSS)」で攻撃してみて、防御できること検証する手順。を記録するもの。

## 内容
- クラウドサービス型のWAF: Web Application Firewall
- WAFはアプリケーションの脆弱性を悪用した攻撃を、ネットワーク機器レベルで防御してくれる。
- 正しく防御してくれるか、わざと脆弱性のあるアプリに攻撃してみる。
- 攻撃は、SQLインジェクションとクロスサイトスクリプティングの２つ。

## 手順の概要
わざと脆弱性のあるWEBサーバーを作って、自分のPCから攻撃する。「WAFが無い場合」と「WAFが有る場合」とで比べる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/aa85032d-a8c4-5bb9-4845-9b96059ee40c.png)

## 今回のシステム構成（必要なモノ）
- 今回メインで試すのは、クラウドWAFとして「**IBM Cloud Internet Services（通称: CIS）**」を使う。
- ドメインは、予算の都合上で「**AWS Route53**」のドメイン名とDNS機能を使う。
- 仮想サーバーは、IBM WAFでマルチクラウドを対象に防御できることを検証するので「**Azure VM**」を使う。
※おおー、これってマッシュアップっていうんじゃなくて？
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/a27b492d-a149-a362-3c4d-502781459f7b.png)

# WEBサーバーの準備
WEBフォームにIDとパスワードを入力すると、個人情報データベースから自分だけのメールアドレスが検索されるプログラムを作る。
サンプルスクリプト等はGithubに保存してあります。

## その１．個人情報データベースのテーブルを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)
```

## その２．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>
```

## その３．データベースを検索する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>
```

## その４．何を入力してもそのまま値を表示する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サーバーの脆弱性を悪用して攻撃してみる
## その１．SQLインジェクション攻撃
### まずは正しい動作から。
自分のIDに対応するメールアドレスだけ表示される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/40e6ff54-6da0-7350-5fb0-6375894cfae6.png)

### 攻撃した場合
パスワード入力欄に「'OR '2' = '2」をインプットするとSELECT文「SELECT email FROM users where uid='$uid' AND passwd='$pass'」のpasswd部分が「誤ったパスワード、もしくは、'2' = '2'」となり常に正しいパスワードだと判断されてデータを取得できちゃう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/5759fc97-ceec-ef45-5f9e-7486bfcf84c3.png)

### WAFが有る場合
先ほどと同じパスワード「'OR '2' = '2」をインプットしてSubmitを押す。ちなみに「' OR 'ABC' = 'ABC」等でもテストできる。WAFがWEBサーバーへのアクセスをブロックした。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/6b9a791f-2dda-7e99-ae47-2e4c7565f784.png)

## その２．クロスサイトスクリプティング［XSS］
### まずは正しい動作から。
入力した名前と年齢をHTMLで表示するだけ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/db79371c-3f4d-8d9f-70df-e03707d6a4c6.png)

### 攻撃した場合（Chromeブラウザ）
名前の入力欄にポップアップしちゃうスクリプト「\<script>alert('攻撃しちゃうぞ');\</script>」をインプットする。ところがchromeブラウザが脅威を検知してしまった。この検証は失敗。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/e35aa3a6-5030-f4c5-603d-624479213774.png)

### 攻撃した場合（IEブラウザ）
今度はIEでスクリプト「\<script>alert('攻撃しちゃうぞ');\</script>」をインプットする。よし、正しく攻撃できた。今回はポップアップだけだが、ここに悪意あるスクリプトを埋め込むと危険。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/cacab021-124c-fc0a-b73e-b45b4a54a0e8.png)

### WAFが有る場合
先ほどと同じスクリプトをインプットすると、WAFが注意画面を表示した。「□私はロボットではありません」にチェックをすると次の画面に進んだ。注意喚起だけなのかな。イベントログにはきちんと記録されていました、「チャレンジ」として。
［後日アップデート］XSSもブロックされるようになりました。イベントログにも「ブロック」として記録されるようになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/b658f2fc-ed9a-107d-0049-b7653a268208.png)
▽イベントログの一部
![image.png](https://qiita-image-store.s3.amazonaws.com/0/189936/55e06034-85d5-f763-7505-bd8fa321f396.png)

## まとめ
WEBサイトをインターネットの脅威から防御するための手段としてWAFを実装する。WAFを初期設定して、きちんとWAF経由で防御できているかを検証するための手順を確認できた。

### 参考
▽IBM Cloud Internet Services (CIS)を使ってみた（オーダー・初期設定）
<<https://qiita.com/y_tama/items/9151b4c981abbb65c53d>>