ALBとCLBに追加されたDesync Mitigation Mode の動作を確認

記事タイトルとURLをコピーする

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が使われているとのことです。

f:id:swx-watanabe:20200821100112p:plain

分類 意味 Monitor mode(モニタリング) Defensive mode(防御的) Strictest mode(最も厳格)
Compliant リクエストはRFC 7230に準拠しており、既知のセキュリティ上の脅威はありません。 許可 許可 許可
Acceptable 要求はRFC 7230に準拠していませんが、既知のセキュリティ上の脅威はありません。 許可 許可 ブロック
Ambiguous リクエストはRFC 7230に準拠していませんが、さまざまなウェブサーバやプロキシが異なる処理をする可能性があるため、リスクがあります。 許可 許可 ブロック
Severe リクエストはRFC 7230に準拠していませんが、さまざまなWebサーバーやプロキシが異なる処理をする可能性があるため、リスクがあります。ロードバランサーはリクエストをブロックし、クライアントに 400 レスポンスを返し、クライアント接続を閉じます。 許可 ブロック ブロック

詳細はAWSのドキュメントに記載があります。

設定

理屈はさておき、設定自体は簡単です。 追加された設定箇所は以下となります。

f:id:swx-watanabe:20200820080234p:plain

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を読んで、いろいろ試していただくといいのではないかと思います。

渡辺 信秀 (記事一覧)