WordPress + AWS WAF設定時の注意点


# はじめに
Wordpressサーバーを運用するにあたり、セキュリティー対策として、AWS　WAFを導入する機会があったのですが、思わぬエラーが出たため、書き留めます。



# 環境構築図
![スクリーンショット 2021-12-26 19.04.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/cc2a87b5-5b60-6732-e289-d8768365038b.png)

# WAFの概要

https://blog.serverworks.co.jp/2020/12/30/090000

# 流れ
1. WAFの導入
1. 導入直後、サイト閲覧
1. 導入後、画像アップロード時、エラー
1. uploadのパスのみ、コアルールセットを適用しない方法
1. 導入後、問い合わせフォームでのエラー
1. ログの保存方法



# WAFの導入
WAFの導入方法についてはこちらの記事を参考にしてください。

https://www.cybermatrix.co/blog/waf/aws-waf-setup-with-managedrule/

ルールの詳細はこちら

https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/aws-managed-rule-groups-list.html

導入方法でも説明されていますが、WAF導入時は必ず`Count`アクションに設定してください。
正しくWordPressのサイトを閲覧していても、どこかで`BLOCK`される可能性があります。

私が今回導入したルールは、こちらです。

- Wordpress application
- SQL database
- PHP application
- Linux operating system
- Core rule set
- Anonymous IP list
- Amazon IP reputation list



# 導入直後、サイト閲覧
導入直後、サイトを適当に閲覧した後に、WAFのCOUNTを確認してみると、`コアルールセット`の`NoUserAgent_HEADER`がCOUNTされていました。

`NoUserAgent_HEADER`とは、「HTTP User-Agent ヘッダーのないリクエストをブロックする」という意味です。
UserAgent_HEADER自体、chromeでは、2023年には、廃止を決めているなど、特にブロックする必要はありません。

そのため、`NoUserAgent_HEADER`は、COUNTモードにしたまま、他のすべてのルールを`BLOCK`にしました。

# 導入後、画像アップロード時、エラー
Wordpressでメディアアップのロードで画像がアップロードできないエラーが発生しました。

![スクリーンショット 2021-12-26 19.29.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/b0f8f758-1e41-79fc-71bd-090cfe6e4de8.png)
![スクリーンショット 2021-12-26 19.30.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/c2a1d472-a8b4-1f24-de86-270cd31d29a7.png)

```
サーバーの負荷が高いか十分なリソースがないため画像の後処理に失敗しました。
もっと小さな画像をアップロードしてみてください。推奨する最大サイズは2500ピクセルです。
```

```
サーバーから予期しないレスポンスがありました。
ファイルは正しくアップロードされているかもしれません。
メディアライブラリもしくはページをリロードして確認してください。
```

WAFを確認してみると、`コアルールセット`の以下2つのルールが`BLOCK`されていました。

### CrossSiteScripting_BODY
組み込み XSS 検出ルールを使用して、URI パスの値を検査し、一般的なクロスサイトスクリプティング (XSS) パターンをブロックします。AWS WAF。パターンの例には、<script>alert("hello")</script> などのスクリプトあります。

### SizeRestrictions_BODY
リクエスト本文のサイズが最大 10,240 バイトを超える場合、ブロックする ​

### SizeRestrictions_QUERYSTRING
URI クエリ文字列の長さが最大 2,048 バイトを超える場合、ブロックする ​

### 対処法は3つ
1. `COUNT`モードにする
2. 管理画面ページを使用するIPが限られている場合、ホワイトリストにIPアドレスを追加します。
1. BLOCKされたURIである`wp-admin/upload.php（仮）`のみコアルールセットを適用せず、他すべてのURIは、上記2つのルールも含めて、すべてのルールを適用する。

セキュリティー面を考えると`2`が最もよいです。

`2`,`3`に関して、方法を説明いたします。

ホワイトリストにIPアドレスを追加する方法は、下記の記事参考にしてください。

https://www.sunnycloud.jp/column/20210601-01/

# uploadのパスのみ、コアルールセットを適用しない方法
1. 正規表現パターンセット（Regex pattern sets）を作成します。![スクリーンショット 2021-12-26 19.48.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/8868b0b9-0996-fdd5-847c-9bbfb570f891.png)

2. ルールグループを作成します。

- 名前を決めます。CloudWatchメトリクスにも記録されるようです。![スクリーンショット 2021-12-26 19.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/94213c31-d514-4a46-ab3a-c297d7fa65e9.png)

- 正規表現パターンセットの`upload`とマッチしたら、`ALLOW`するルールを作成します。日本語訳するとわかりやすいです。
![スクリーンショット 2021-12-26 20.04.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/b0ba7d0e-84a9-1d86-e17e-468642a62a2d.png)

↓日本語訳

![スクリーンショット 2021-12-26 20.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/ad5a7159-d61e-1787-5554-1f8a2fd49f17.png)

作成したルールグループをWAFに加え、コアルールセットよりも優先順位を高くすると、`wp-admin/upload.php`のみコアルールセットが適用されずに、`ALLOW`されます。

ちなみに`wp-admin/upload.php`以外のパスもコアルールセットに入れたくない場合、`正規表現パターンセット`を作成し、`ルールグループ`に追加するとよいです。


# WAF導入後、問い合わせフォームでのエラー
問い合わせフォームを送るとき、エラーが起き、送れませんでした。
コアルールセットの以下1つが`BLOCK`されていました。

### GenericRFI_BODY
リクエスト本文の値を検査し、ウェブアプリケーションの RFI (リモートファイルインクルージョン) を悪用しようとするリクエストをブロックします。パターンの例には、:// などがあります。

先程の対処法を参考に、対処しましょう。

# WAF導入後、phpMyAdminでsqlのエクスポートができない(404エラー)

`AWSManagedRulesSQLiRuleSet`の`SQLi_QUERYARGUMENTS`のルールでブロックされていました。

### SQLi_QUERYARGUMENTS
組み込みの AWS WAF SQL インジェクション match ステートメントを使用して、すべてのクエリパラメータの値に、悪意のある SQL コードに一致するパターンがないかを検査します。

### 対処法
こちらは、sqlのエクスポートするIPが特定している場合、特定のIPのみ許可（ホワイトリスト）するようにしましょう。
先程の対処法は、パスに対して、コアルールセットよりもルールグループを優先させる方法でしたので、
同様にパスではなく、特定のIPのルールグループを作成し、`AWSManagedRulesSQLiRuleSet`よりもルールグループを優先させるとよいです。


# WordPressでBLOCKされやすいWAFルール
今回のWordPressにWAFを適用するにあたり、以下の4つのルールが`BLOCK`されましたので、`COUNT`にしております。
もしくは、特定のIPや特定のパスのみルールを適用しない方法もありますので、状況に応じて対応しましょう。
同様の構築をする際に、参考になればと思います。

**コアルールセット**:`AWSManagedRulesCommonRuleSet`

|ルール |意味|
|---|---|
| NoUserAgent_HEADER | HTTP User-Agent ヘッダーのないリクエストをブロックする |
| CrossSiteScripting_BODY | 組み込み XSS 検出ルールを使用して、URI パスの値を検査し、一般的なクロスサイトスクリプティング (XSS) パターンをブロックします。AWS WAF。パターンの例には、 などのスクリプトあります。 |
| SizeRestrictions_BODY | リクエスト本文のサイズが最大 10,240 バイトを超える場合、ブロックする |
| SizeRestrictions_QUERYSTRING | URI クエリ文字列の長さが最大 2,048 バイトであることを確認します。|
| GenericRFI_BODY | リクエスト本文の値を検査し、ウェブアプリケーションの RFI (リモートファイルインクルージョン) を悪用しようとするリクエストをブロックします。パターンの例には、:// などがあります。 |


**SQL データベース**:`AWSManagedRulesSQLiRuleSet`

|ルール |意味|
|---|---|
| SQLi_QUERYARGUMENTS | 組み込みの AWS WAF SQL インジェクション match ステートメントを使用して、すべてのクエリパラメータの値に、悪意のある SQL コードに一致するパターンがないかを検査します。 |

# ログの保存方法


下記の記事通りすると、`COUNT`と`BLOCK`のみWloudWatchLogsに保存できます。

https://dev.classmethod.jp/articles/awswaf-support-log-filtering/

- 「aws-waf-logs-」で始まるロググループを作成する必要あり