■WAF
Web Application Firewall
CloudFrontやロードバランサーにファイヤーウォールを設定し、不正なアクセスをブロックできる
SQLインジェクションなどに対応できる
セキュリティグループとは特性の違う攻撃の対策になる
ただしセキュリティグループとは違って若干お金はかかる
AWS WAFでSQLインジェクションをブロックしてみた | Developers.IO
http://dev.classmethod.jp/cloud/aws/aws-waf-sqli/
AWS WAFがALB(Application Load Balancer)で利用出来るようになりました
http://dev.classmethod.jp/cloud/aws/aws-waf-alb-support/
AWS WAF を急に導入することになったときに参考にした資料まとめ | DevelopersIO
https://dev.classmethod.jp/articles/blog-links-for-aws-waf-configuration/
※以前はCloudFrontが必須だったが、現在はALBでも使えるようになっている
ELBを導入済みの場合、ALBに変更することでWAFを使えるようになる
WAFを設定することにより、ファイルアップロードの実装が難しくなるなどのデメリットがある
詳細は後述の「誤検知対策」を参照
以下にVer2の解説がある
操作方法が大きく変わっているので注意
AWS WAFを完全に理解する ~WAFの基礎からv2の変更点まで~ | Developers.IO
https://dev.classmethod.jp/cloud/aws/fully-understood-aws-waf-v2/
以下、Ver2で検証したもの
■テストページ
index.php:
<html>
<meta charset="UTF-8">
<head>
<title>ログイン画面</title>
</head>
<body>
<form action="db.php" method="post">
<table>
<tr>
<td>ユーザID</td>
<td><input type="text" name="uid"></td>
</tr>
<tr>
<td>パスワード</td>
<td><input type="password" name="password"></td>
</tr>
</table>
<input type="submit" value="ログイン">
</form>
</body>
</html>
db.php:
<html>
<meta charset="UTF-8">
<head>
<title>ログイン処理</title>
</head>
<body>
<pre><?php
$uid = $_POST['uid'];
$pass = $_POST['password'];
print("SELECT email FROM users WHERE uid='$uid' AND passwd='{$pass}'");
?></pre>
</body>
</html>
ブラウザからindex.phpにアクセスし、
ユーザID: test
パスワード: test
で認証すれば通常通り処理されるが、
ユーザID: test
パスワード: ' OR 'A' = 'A
で認証すれば「403 Forbidden」と表示される(WAFで入力を弾いている)
…となるように以降で設定する
■WAFを導入
SQLi と XSS を防ぐための AWS WAF ルール
https://aws.amazon.com/jp/premiumsupport/knowledge-center/waf-rule-prevent-sqli-xss/
WAF & Shield → Create web ACL
Step 1: Describe web ACL and associate it to AWS resources
Name: test
CloudWatch metric name: test(自動で入力される)
Resource type: Regional resources(CloudFrontに対して設定したい場合、「CloudFront distributions」にする)
Region: Asia Pacific (Tokyo)
Associated AWS resources: study(ここでは、テストで作成したALBを選択した)
「Next」ボタンを押す
Step 2: Add rules and rule groups
「Add rules → Add my own rules and rule groups」をクリック
Rule type: Rule builder
Name: SQL-injection
Type: Regular rule
If a request: matchs the statement
Inspect: Body(HTMLフォームを検査する)
Content type: Plain text
Match type: Contains SQL injection attacks
Text transformation: URL decode(URLデコードを行った後で検査する)
Oversize handling: Continue
Sensitivity level: Low
Action: Block
「Add rule」をクリックし、ページ上部の「Rules」部分にルールが追加されたことを確認する
Default action: Allow(デフォルトのまま)
「Next」ボタンを押す
Step 3: Set rule priority
そのまま「Next」ボタンを押す
Step 4: Configure metrics
そのまま「Next」ボタンを押す
Step 5: Review and create web ACL
内容を確認して「Create web ACL」ボタンを押す
■動作確認
http://203.0.113.1/waf/ ... ALBを経由しないアクセスなのでWAFは無効になっている
http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/ ... ALBに対して設定したのでWAFが有効になっている
WAFは、なるべく後ろにある方が良さそう
基本的にCloudFrontに対してよりも、ALBに対してWAFを設定すると良さそう
(AWSへの直接アクセスを禁止するなら、CloudFrontへの設定でいい)
WAFが機能しない場合、意図したAWSリソースが選択されているかなどを確認する
■XSS対策の例
「WAFを導入」と基本的には同じ手順で導入できる
その際、「Step 2」の操作内容は以下のようにする
もし登録済みのWeb ACLがあれば、「Rules」タブからルールを追加することもできる
Step 2: Add rules and rule groups
「Add rules → Add my own rules and rule groups」をクリック
Rule type: Rule builder
Name: XSS-injection
Type: Regular rule
If a request: matchs the statement
Inspect: Body(HTMLフォームを検査する)
Content type: Plain text
Match type: Contains XSS injection attacks
Text transformation: URL decode(URLデコードを行った後で検査する)
Oversize handling: Continue
Action: Block
「Add rule」をクリックし、ルールが追加されたことを確認する
これで
ユーザID: test
パスワード: <script>window.alert(1)</script>
で認証すれば「403 Forbidden」と表示される(WAFで入力を弾いている)
■IP制限の例
AWS WAFV2でIPアドレス制限してみた | DevelopersIO
https://dev.classmethod.jp/articles/how-to-use-aws-waf-v2-to-filter-incoming-traffic-based-ip-addres...
練習を兼ねて&即座にIP制限ができるように、IP制限の設定だけは最初にしておくといい
以下は設定を試したときのメモ
この場合、「192.0.2.1」からのアクセスが拒否される
WAF & Shield → IP sets → Create IP set
IP set name: Black-List
Region: Asia Pacific (Tokyo)
IP version: IPv4
IP addresses: 192.0.2.1/32
以降は「WAFを導入」と基本的には同じ手順で導入できる
その際、「Step 2」の操作内容は以下のようにする
もし登録済みのWeb ACLがあれば、「Rules」タブからルールを追加することもできる
Step 2: Add rules and rule groups
「Add rules → Add my own rules and rule groups」をクリック
Rule type: IP set
Name: IP-Restriction
IP set: Black-List(上の手順で作成したものを選択)
IP address to use as the originating address: Source IP address
Action: Block
「Add rule」をクリックし、ルールが追加されたことを確認する
これで「Black-List」のIPアドレスを更新することで、IP制限を行うことができる
(反映には、10〜20秒ほどのタイムラグがある)
制限対象とするIPアドレスは、「WAF & Shield → IP sets → Black-List」の画面から追加削除できる
■大量アクセスを自動的にIP制限する例
AWS WAF でアクセス数が一定回数を超えた IP アドレスを自動的にブラックリストに追加させる方法 | DevelopersIO
https://dev.classmethod.jp/articles/tsnote-aws-waf-autoblock/
「WAFを導入」と基本的には同じ手順で導入できる
その際、「Step 2」の操作内容は以下のようにする
もし登録済みのWeb ACLがあれば、「Rules」タブからルールを追加することもできる
Step 2: Add rules and rule groups
「Add rules → Add my own rules and rule groups」をクリック
Rule type: Rule builder
Name: DoS-Protection
Type: Rate-based rule
Rate limit: 100(最小値が100)
IP address to use for rate limiting: Source IP address
Criteria to count request towards rate limit: Consider all requests(特定パス配下にのみ設定したければ「Only consider requests that match the criteria in a rule statement」を選択し、追加で必要な設定を行う)
Action: Block
「Add rule」をクリックし、ルールが追加されたことを確認する
これで大量アクセスすると自動でブロックされる
Web ACLs「test」の「Overview」で「DoS-Protection BlockedRequests 200」を確認できる。200回ブロックされたということだと思われる
$ curl -I http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/
HTTP/1.1 200 OK
Date: Thu, 12 Jan 2023 10:41:33 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Server: Apache/2.4.54 ()
X-Powered-By: PHP/8.1.12
Upgrade: h2,h2c
$ ab -n 10 -c 1 http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/
Complete requests: 10
Failed requests: 0
$ ab -n 100 -c 1 http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/
Complete requests: 100
Failed requests: 0
$ ab -n 200 -c 1 http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/
Complete requests: 200
Failed requests: 0
$ ab -n 300 -c 1 http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/
Complete requests: 300
Failed requests: 0
以下のように403エラーが返されるようになったが、上記のように「Failed requests」にはカウントされないみたい
また、403エラーが返されるようになるまで数分のタイムラグがあった
$ curl http://develop-123456789.ap-northeast-1.elb.amazonaws.com/waf/ --verbose
* Trying 203.0.113.1:80...
* Connected to develop-123456789.ap-northeast-1.elb.amazonaws.com (203.0.113.1) port 80 (#0)
> GET /test/ HTTP/1.1
> Host: develop-123456789.ap-northeast-1.elb.amazonaws.com
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< Server: awselb/2.0
< Date: Fri, 13 Jan 2023 06:25:44 GMT
< Content-Type: text/html
< Content-Length: 118
< Connection: keep-alive
<
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
</body>
</html>
* Connection #0 to host develop-123456789.ap-northeast-1.elb.amazonaws.com left intact
ブロックされたリクエストは、Web ACLs「test」の「Overview」の「Sampled requests」で確認できるみたい
IPアドレスや対象URLなどを確認できる
(受信したリクエストから、AWS WAFがランダムに選択したものが表示されるみたい
すべてのログを記録する場合、「Logging and metrics」タブから設定できるみたい)
また、このIP制限は一定時間が経過すると自動で解除される
30分ほどで自動解除されていることは確認できた(大量アクセスが落ち着いたら時点で解除されるのかもしれない)
■その他の制限例
AWS WAFで日本国外からのアクセスをブロックする - サーバーワークスエンジニアブログ
https://blog.serverworks.co.jp/aws-waf-block-from-overseas-countries
AWS WAF で Bot からのアクセスを管理する Bot Control が利用可能になりました! | DevelopersIO
https://dev.classmethod.jp/articles/aws-bot-control/
[アップデート]AWS WAFのBot Controlルールグループに検査レベル「Targeted」が追加され、新たに4つのインテリジェントなルールが利用可能になりました | DevelopersIO
https://dev.classmethod.jp/articles/aws-waf-targeted-bot/
レートベースルールで検知したIPをIP Setに登録する | DevelopersIO
https://dev.classmethod.jp/articles/add-ratebase-rule-deny-ip/
■ブロック時の画面をカスタマイズする
WAFで制限されると、そのリクエストの画面には「403 Forbidden」とだけ表示される
これだけだと何の影響でエラーになっているのか判りづらいので、問い合わせ対応のためにも独自のメッセージを表示させておくといい
AWS WAFの機能だけでブロック時にカスタムエラーページを表示させてみた | DevelopersIO
https://dev.classmethod.jp/articles/aws-waf-custom-response_bodies_html/
WAFの設定画面でルールを追加する際、Actionで「Block」を選択してCustom response内で以下のように設定する
Enable: (チェックを入れる)
Response code: 403
Choose how you would like to specify the response body: Create a custom response body
すると「Create a custom response body」というダイアログが開くので、以下のように登録する
Response body object name: 403
Content type: HTML
Response body: (任意のHTML)
登録した内容は、次回からは「Choose how you would like to specify the response body」の選択肢に表示される
「任意のHTML」は4KB以内で作成する
また、ヘッダでUTF-8を宣言しておくといい
以下は具体的なHTMLの例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>403 Forbidden</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
</head>
<body>
<h1>403 Forbidden</h1>
<p>ウェブアプリケーションファイアウォールによりアクセスが遮断されました。</p>
<p><a href="/">トップページへ戻る</a></p>
</body>
</html>
■マネージドルール
ルールを追加する際、「Add my own rules and rule groups」ではなく「Add managed rule groups」を選択するとマネージドルールの選択画面になる
あらかじめ定義されたルールを適用できるので、運用を楽にすることはできそうだが、利用料金がかかるので注意
AWS WAF向けマネージドルールのおすすめは?種類別サービス7選|アスピック
https://www.aspicjapan.org/asu/article/11671
■誤検知対策
ロリポップのWAFは、有効にするとWordPressなどがまともに動かなくなるらしい
記事投稿時にWAFをOFFにするか、常にWAFをOFFにするか…のように紹介されている
WordPress403 Forbiddenの原因はWAF!対処し解決する方法!:ロリポップ、さくら、ヘテムルのサーバー
http://bibabosi-rizumu.com/403error-forbidden/
ロリポップ+WordPress+Contact Form 7でWAFが誤動作してForbiddenになるんだけどどういうことなの | texst.net
http://texst.net/lolipop-waf-wordpress-cf7-forbidden/
AWSのWAFも同じことになる可能性はあるが、
「AWS Black Belt Tech Webinar 2015 ‐ AWS WAF」レポート | Developers.IO
http://dev.classmethod.jp/cloud/aws/blackbelt2015-waf/
にて
「これまでのWAF: 誤検知 (false positive) が増えて悩むことになった」
「AWS WAFには、次のような特長がある: ルールを柔軟にカスタマイズできる」
のように紹介されている。柔軟にカスタマイズすることで、誤検知の対策はできるのかも。要勉強
本番環境でWAFを導入する場合、テスト段階でも導入して動作確認しておかないと、
アプリケーションが正しく動作しない可能性がありそうなので注意
…と思いつつ案件に本格導入しようとしたが、検収環境での検証時に「ファイルをアップロードできない」という問題が発生した
AWS WAF について最初から知りたかったこと8選 - ISID テックブログ
https://tech.isid.co.jp/entry/8_things_i_wanted_to_know_about_aws_waf
AWS WAF によってブロックされたファイルのアップロード
https://aws.amazon.com/jp/premiumsupport/knowledge-center/waf-upload-blocked-files/
【AWS】特定のURIリクエストのみAWS WAFルールを適用させない方法 - Qiita
https://qiita.com/yokoo-an209/items/7037aed6fbe18fb4c659
WordPress + AWS WAF設定時の注意点 - Qiita
https://qiita.com/hirai-11/items/252705c33914dcab000c
AWS上のWebシステムへのファイルアップロード時にAWS WAFでブロックされる。
https://teratail.com/questions/heafxwwa3541vz
AWS WAFのマネージドルールでありがちな予期せぬブロック(随時更新) - mazyu36の日記
https://mazyu36.hatenablog.com/entry/2023/02/21/191736
AWS WAF を本適用の前にカウントモードで試用したい - DENET 技術ブログ
https://blog.denet.co.jp/aws-waf-count/
現状「ファイルアップロードは除外」などは対応不可らしい
対応するなら「WAFに対して(あらかじめ安全だと確認できている)特定のURI時のリクエストに対してブロックルールを適用しない」とする必要があるらしい
…が、本番環境に導入したら
「特定のURLから投稿できない。ルールの調整を忘れていた」
「ここは問題無いと思っていたがWAFに引っかかった」
が時々発生して障害になりそうな。他にも、新たな問題が発覚したりはありそうな
よって、2023年3月時点では導入を見送った
■メモ
AWS Shield はDDoS攻撃を緩和させるサービス
Standardは自動で適用されているため、ユーザ側での設定は不要
Advancedにするには、AWSサポートのビジネスレベルかエンタープライズレベルである必要がある
5分で分かるAWS Shield
https://recipe.kc-cloud.jp/archives/9009
ただし運用していてDos攻撃を受けることはあるので、どの程度機能しているのかは不明
以下などのように、攻撃してきたIPアドレスを自動で弾くなどの対策が必要そう
AWS WAFを使って簡単にDoS攻撃を防いでみよう【セキュリティ対策】 | レコチョクのエンジニアブログ
https://techblog.recochoku.jp/4070