AWS WAFの導入

AWS WAF(v2)についてまとめます。

## AWS WAFとは
AWSが提供するWAF(Web Application Firewall)です。SQLインジェクションやXSSなどのWebアプリケーションに対する攻撃から対象のリソースを保護します。リソースとして指定できるのは↓です(2020年11月現在)。

* Amazon CloudFront 
* Amazon API Gateway 
* Application Load Balancer
* AWS AppSync GraphQL API

## WebACL
### WebACLとは

* ルールを入れる箱のこと
* ACLにルールを追加していき、攻撃に対する戦略を定義する
* ステートメント：リクエストを検査するための条件を定義
* アクション：ステートメントに一致した場合の処理方法　
* WCU：ACLに収容できるルールの上限

### アクションの種類
ルールに対して設定できる[アクション]((https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-rule-action.html)
)は3つあります。

| アクション |  ルールに一致した場合の挙動 | 
| -------- | -------- | 
| Allow| リクエストを許可|
| Block| リクエストをブロック|
| Count |リクエストを許可も拒否もせず、カウントとして検知。他のルールとも照合していき、最終的にデフォルトのアクションを実行|

### マネージドルール
あらかじめAWS側で用意した、一般的なWebアプリケーション攻撃に対応するルールのセット。マネージドルールを使うことで、自分でルールをセットする必要がなくなる
* [AWS Managed Rules rule groups リスト](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/aws-managed-rule-groups-list.html)

マネージドルールの選び方は↓が参考になる
* [AWS Managed Rules の選び方](https://www.wafcharm.com/blog/how-to-choose-aws-managed-rules/)

### レートベースのルール（同一IPからの大量リクエストのブロック）
* ５分間あたりの同一IPアドレスからのリクエスト数が設定された閾値を超過したらBlock/Countする
* 閾値の設定範囲は100~20,000,000で設定
* ルール作成時にRate-based Ruleを選択
* 全てのリクエストを対象にするか、ステートメント内の条件に一致したリクエストだけを対象にするか選択可能

### 独自ルールの設定パターン
* Match  
    * Statement（条件）に定義されたルールに一致する場合にアクションを実施
    * 例）アクセス元IPがルールセットに合致する場合ブロック
* Not 
    * Statementに定義されたルールに一致しない場合にアクションを実施
    * 例）アクセス元が日本ではない場合にブロック
* AND
    * 全てのStatementに定義されたルールに一致する場合にアクションを実施
    * 例
        * 特定の国からのアクセスかつ、URLに特定のパスが含まれる場合にブロック
        * クエリパラメーターにadminの文字列を含むリクエストかつ、リクエストbodyがXSSの攻撃内容が含まれる場合にブロック
        * 特定の国からのリクエストのURI のパスに「login」を含むかつ、リクエストのレートが1,000を超える場合にブロック
* OR
    * いずれかのStatementに定義されたルールに一致する場合にアクションを実施
    * 例）特定にIPまたは特定の国からのアクセスであればブロック

## DDoS対策
* AWS Shield StandardとAWS WAFを組み合わせることで基本的なDDoS対策が可能
* L3/L4への攻撃→AWS Shield Standardで防御。設定不要。全てのAWSサービスで有効化されている
* L7への攻撃→AWS WAFのレートコントロールにより防御可能
* 参考：[Edge Servicesを利用したDDoS防御の構成（AWS WAF/Shield） | AWS Summit Tokyo 2019](https://www.youtube.com/watch?v=f2VU_TtwANc&ab_channel=AmazonWebServicesJapan%E5%85%AC%E5%BC%8F)より

## WAFの導入ステップ

### ルールの決め方
#### ブラックリスト型
* デフォルトのアクションは許可
* ルールに合致した不正なリクエストをブロック
* 一般的なwebサイト向け

#### ホワイトリスト型
* デフォルトのアクションはブロック
* ルールに合致したリクエストのみを許可
* 全てのリクエストパターンが事前に把握できる場合で、限られた利用者がアクセスするケース向け

### ブロック→カウントへの移行
* AWS WAFの導入時点でいきなりルールに対してブロックをかけてしまうと、本来許可すべきリクエストまでブロックしてしまう可能性があります。そのため、最初は各ルールに対するアクションをカウント（検知するのみ）にし、どのようなアクセスがマネージドルールで検知されるかをテスト環境などで検証します。ルールごとに段階的にCount→Blockに切り替えるのもありです。

> AWS WAF ではルールの条件に合ったウェブリクエストの数をカウントでき、ルールの「カウント」のアクションを設定できます。ルールを有効にすると、どれだけのウェブリクエストがブロックまたは許可されるかをカウントされたウェブリクエストの数から推定できます。([よくある質問](https://aws.amazon.com/jp/waf/faq/#:~:text=AWS%20WAF%20allows%20you%20to,5.))
* [テスト用ウェブ ACLs](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/web-acl-testing.html)

## マネジメントコンソールからの設定方法
* Create Web ACLをクリックし項目を埋める
![100853355-04e42c80-34cb-11eb-967b-c2571ab61b54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/e6405d2e-dd48-1072-80d0-47da42789c34.png)

* 設定したいマネージドルールを選択
![100853371-09104a00-34cb-11eb-9796-405594f7cc23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/149fb801-e632-3bd3-bb8b-5638c0b43cfe.png)


* デフォルトアクションAllowで進む
![100853376-0a417700-34cb-11eb-8a05-3b6bc3f20a7b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/62b2c5ca-3aee-45e8-4380-d99620496e03.png)

* ルールのプライオリティを決める
![100853384-0d3c6780-34cb-11eb-8a00-abab1830f634.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/d045038c-8055-fc2c-9a10-70c8a392efe4.png)

* ClowdWatchのメトリクス名を決める。デフォルトのままでもOK
![100853388-0e6d9480-34cb-11eb-97a4-d85ae9a98871.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/5e9891d3-775d-d1f0-f075-b5f5e02ada7a.png)

設定してからサンプルリクエストに反映されるまで10分くらいかかる

## 挙動の確認（レートベースのルール）

試しにレートベースルールの下限100リクエスト/5分でブロックに設定
AppachBenchを使ってbastionから100以上のリクエストを送信

```
ab -n 110 -c 1 http://xxxx.xxx.xxx
```
1分程度でブロックされる

```
curl http://xxxx.xxx.xxx
```

## ロギング
### サンプルログ
* 受信した最初の5,000リクエストからAWS WAFがランダムに選択したものが記録される。
* AWS WAFの導入テスト向け
* 直近3週間分しか閲覧できない

### フルログ（オプション）
* 全リクエストの詳細ログ
* Kinesis Data Firehose経由でS3に保存が可能
* あらかじめ'aws-waf-logs-'のプレフィックスをつけたdelivery streamを作成しておく
* WebACLを選択 > Logging and metrics > Enable logging

![120740945-246a1980-c52f-11eb-96cd-9114f93f733b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260824/d94aa9b9-e638-b6d6-5621-b642c3d6a4af.png)

## 参考
### 公式
* [公式ドキュメント](https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/how-aws-waf-works.html)
* [[AWS Black Belt Online Seminar] AWS WAFアップデート 資料及び QA 公開](https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-waf-update-2020/)
* [既知の望まないホストの攻撃から Elastic Beanstalk 環境を保護するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/elastic-beanstalk-host-attacks/)
### その他
* [AWS WAFマネージドルール導入と運用の勘所](https://dev.classmethod.jp/articles/howto-waf-managedrule/)
* [[Security] [初心者向け]AWS環境のセキュリティ運用(設計)をはじめてみよう](https://jawsdays2019.jaws-ug.jp/session/1270/)
* [AWS WAFを使って簡単にDoS攻撃を防いでみよう](https://techblog.recochoku.jp/4070)