2020年8月17日のアップデートです。 ALBとCLBに Desync 緩和モード という設定項目が追加されました。 これはセキュリティ強化のための機能となります。
Application Load Balancer および Classic Load Balancer が Desync Mitigation Mode を導入して高度な防御を追加
HTTPメッセージの解釈ブレが原因の脆弱性
HTTP/1.1のメッセージの文法の標準化はRFC 7230で策定されています。ところが、実際に世の中で動いているWebサーバやプロキシサーバは厳密にRFC7230を遵守しているわけではありません。 同じメッセージを送っても異なる振る舞いをすることがあります。ブラウザとWebサーバが直接通信をしている場合はあまり問題がないようですが、プロキシサーバが中間に入り、Webサーバと異なる動作をする場合に成立する攻撃があります。
どのような攻撃がありうるかは、「HTTP Request Smuggling」「HTTP Desync Attacks」で検索していただければと思います。
ALBやCLBはプロキシサーバに該当するため、脆弱性が入り込む余地があります。
Desync 緩和モードとは
「それなら脆弱性が入り込まないように、ALBとCLBでHTTPメッセージをもっとちゃんとチェックしようやないかー」ということで今回の Desync 緩和モード が追加されました。
ALBとCLBがHTTPリクエストを受け取ると、その中身を検査し、「Compliant」 「Acceptable」 「Ambiguous」 「Severe」 のいずれかに分類します。分類後、Desync 緩和モードの設定値によって、リクエストは 「許可」 または 「ブロック」 されます。
分類にはhttp-desync-guardianというAWSのOSSが使われているとのことです。
分類 | 意味 | Monitor mode(モニタリング) | Defensive mode(防御的) | Strictest mode(最も厳格) |
---|---|---|---|---|
Compliant | リクエストはRFC 7230に準拠しており、既知のセキュリティ上の脅威はありません。 | 許可 | 許可 | 許可 |
Acceptable | 要求はRFC 7230に準拠していませんが、既知のセキュリティ上の脅威はありません。 | 許可 | 許可 | ブロック |
Ambiguous | リクエストはRFC 7230に準拠していませんが、さまざまなウェブサーバやプロキシが異なる処理をする可能性があるため、リスクがあります。 | 許可 | 許可 | ブロック |
Severe | リクエストはRFC 7230に準拠していませんが、さまざまなWebサーバーやプロキシが異なる処理をする可能性があるため、リスクがあります。ロードバランサーはリクエストをブロックし、クライアントに 400 レスポンスを返し、クライアント接続を閉じます。 | 許可 | ブロック | ブロック |
詳細はAWSのドキュメントに記載があります。
設定
理屈はさておき、設定自体は簡単です。 追加された設定箇所は以下となります。
ALBを作成すると、デフォルトで Desync 緩和モード が Defensive mode(防御的) になります。また、この設定が追加される前に作成されたALBの設定も同様に Defensive mode になっています。
動作確認
各モードで動作が本当に変わるのか確認してみました。 aws/http-desync-guardianを読んだのですが、実際にブロックパターンと判断されるアクセスを試行するのが困難でした。
あまり意味のあるアクセスではないかもしれませんが、モードによって挙動が異なるアクセスパターンが確認できましたので、紹介します。
正常なアクセス
Testと書かれたテキストファイルをGetするcurlコマンドです。Getなので通常はデータを送信しないためContent-Lengthヘッダは不要です。
リクエスト
~$ curl -v http://test-alb-1685957578.ap-northeast-1.elb.amazonaws.com/test.html * Trying 52.196.112.40... * TCP_NODELAY set * Connected to test-alb-1685957578.ap-northeast-1.elb.amazonaws.com (52.196.112.40) port 80 (#0) > GET /test.html HTTP/1.1 > Host: test-alb-1685957578.ap-northeast-1.elb.amazonaws.com > User-Agent: curl/7.64.1 > Accept: */* >
レスポンス
< HTTP/1.1 200 OK < Date: Fri, 21 Aug 2020 01:19:04 GMT < Content-Type: text/html; charset=UTF-8 < Content-Length: 5 < Connection: keep-alive < Server: Apache/2.4.43 () PHP/5.4.16 < Upgrade: h2,h2c < Last-Modified: Thu, 20 Aug 2020 22:58:34 GMT < ETag: "5-5ad570f55d342" < Accept-Ranges: bytes < Test * Connection #0 to host test-alb-1685957578.ap-northeast-1.elb.amazonaws.com left intact * Closing connection 0
問題のあるアクセス
あえてContent-Length: 0を入れてみます。
リクエスト
~$ curl -v -H "Content-Length: 0" http://test-alb-1685957578.ap-northeast-1.elb.amazonaws.com/test.html * Trying 52.69.148.157... * TCP_NODELAY set * Connected to test-alb-1685957578.ap-northeast-1.elb.amazonaws.com (52.69.148.157) port 80 (#0) > GET /test.html HTTP/1.1 > Host: test-alb-1685957578.ap-northeast-1.elb.amazonaws.com > User-Agent: curl/7.64.1 > Accept: */* > Content-Length: 0 >
レスポンス
モニタリング または 防御的 の場合
Content-Lengthがない時と同じ動作をします。
< HTTP/1.1 200 OK < Date: Fri, 21 Aug 2020 01:21:24 GMT < Content-Type: text/html; charset=UTF-8 < Content-Length: 5 < Connection: keep-alive < Server: Apache/2.4.43 () PHP/5.4.16 < Upgrade: h2,h2c < Last-Modified: Thu, 20 Aug 2020 22:58:34 GMT < ETag: "5-5ad570f55d342" < Accept-Ranges: bytes < Test * Connection #0 to host test-alb-1685957578.ap-northeast-1.elb.amazonaws.com left intact * Closing connection 0
なお、これは余談ですが、Content-Lengthを1以上の数値にすると、Webサーバが「408 Request Timeout」を返しました。
最も厳格 の場合
リクエストはWebサーバに届かず、ALBが「400 Bad Request」を返します。
< HTTP/1.1 400 Bad Request < Server: awselb/2.0 < Date: Fri, 21 Aug 2020 01:24:39 GMT < Content-Type: text/html < Content-Length: 138 < Connection: close < <html> <head><title>400 Bad Request</title></head> <body bgcolor="white"> <center><h1>400 Bad Request</h1></center> </body> </html> * Closing connection 0
ALBのログ
以下のような感じで、Ambiguous、UndefinedContentLengthSemanticsといったものが見られました。 これが何かは、http-desync-guardianで確認できます。
http 2020-08-21T00:35:54.382266Z app/test-alb/66605c670e203812 xx.xx.xx.xx:xxxx - -1 -1 -1 400 - 144 288 "GET http://test-alb-1685957578.ap-northeast-1.elb.amazonaws.com:80/test.html HTTP/1.1" "curl/7.64.1" - - - "-" "-" "-" - 2020-08-21T00:35:54.375000Z "-" "-" "-" "-" "-" "Ambiguous" "UndefinedContentLengthSemantics"
まとめ
ALBとCLBでHTTPメッセージをどこまで厳格に解釈し振舞うかについて、3つのモードが選択できるようになりました。デフォルトのモードは防御的ですが、よりセキュリティを高めたい場合はaws/http-desync-guardianを読んで、いろいろ試していただくといいのではないかと思います。
渡辺 信秀(記事一覧)
2017年入社 / 地味な内容を丁寧に書きたい