AWS WAF で対策できること

AWS WAF の詳細 - AWS WAF、AWS Firewall Manager、および AWS Shield アドバンスド

WAF はその名の通りアプリケーションレベルのアタックを防ぐことを目的としている. CloudFront もしくは ELB に組み込んで使用する.

対象となる HTTP リクエストの項目

  • ヘッダ
  • メソッド
  • クエリ文字列
  • クエリパラメータ (value)
  • URI
  • ボディ
  • 発信元 IP アドレス
  • 発信元地域

各項目のチェック内容

  • サイズ (bytes)
  • 文字列比較 (正規表現対応)
  • XSS
  • CSRF
  • SQL インジェクション

実装によるが,例えばリクエストボディをバイナリにシリアライズすると WAF からはボディの中身を読めなくなる. AWS WAF のインスペクタがデコードできるのは HTML, URL, Base64 などに限られるためである.シリアライザを使いつつ WAF でリクエストボディをチェックするとすればサイズをチェックするしかない.この場合,ボディの中身をチェックするのはデシリアライズ後になる.つまりはサーバサイドプログラムでチェックすることになる.

使ってみる

前提

クライアントからのリクエストは CloudFront + WAF で処理され, allow されたリクエストのみが Nginx に渡される. Nginx は正常なアクセスに対して “Hi!” とレスポンスを返す.

WAF のルール

リクエストボディに “hoge” という文字列が含まれていたらブロックする.

WAF インスペクタ

正常なアクセスの場合

CloudFront 経由で Nginx から 200 が返る.

curl -i 'https://example.cloudfront.net'
HTTP/2 200
content-type: text/html
content-length: 4
server: nginx/1.12.1
date: Fri, 09 Nov 2018 06:43:25 GMT
last-modified: Thu, 01 Nov 2018 04:20:13 GMT
etag: "5bda7efd-4"
accept-ranges: bytes
x-cache: RefreshHit from cloudfront
via: 1.1 2884f0fcb5b8a2bdfa5376dd5f29da92.cloudfront.net (CloudFront)
x-amz-cf-id: QdCpHpH9zFBOYXXWe52jKZIyrc4nE5FqwdEgGtgtYwdva6Xr4mDSjQ==

Hi!

アタックの場合

POST でリクエストボディとして “hoge” を送ると 403 が返る.このとき,クライアントからのリクエストは CloudFront + WAF だけで処理されており Nginx まで届いていない. Nginx (Origin) に負荷がかからないのでありがたい.

curl -i 'https://example.cloudfront.net' -d "hoge"
HTTP/2 403
server: CloudFront
date: Fri, 09 Nov 2018 08:47:45 GMT
content-type: text/html
content-length: 560
x-cache: Error from cloudfront
via: 1.1 2005babf9e16815c80be6808c6f595b1.cloudfront.net (CloudFront)
x-amz-cf-id: js8hupWc1ve4sxDTsFfp7DRqEY3PtwV-JtiRqEOkoSeeR1us36j48A==

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Request blocked.

<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: js8hupWc1ve4sxDTsFfp7DRqEY3PtwV-JtiRqEOkoSeeR1us36j48A==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>

テンプレート

設定のテンプレートが色々用意されている.とりあえず OWASP’s Top 10 あたりを仕込んでおけばよいと思われる.さすがに一からルールを設定するのは骨が折れる.

これで定番のアタックはおおよそ防げるようになる. False-positive になりそうなルールは適宜削除する.