HTTP request smuggling
X(旧Twitter)で存在を知り聞いたことのなかった脆弱性であったため、調べたことをまとめた
HTTP request smugglingとは?
フロントエンドのWebサーバー(リバースプロキシやロードバランサーなど)とバックエンドのWebサーバーに対して攻撃者によって作成された不正なHTTPリクエストを異なる解釈で行ってしまうことで発生する脆弱性
通常処理
フロントエンドサーバーはHTTPリクエストをバックエンドサーバーに転送する際、同じバックエンドネットワークを通じて、複数のリクエストを送信する必要がある。
そのため次々に送られてくるHTTPリクエストに対して受信するサーバーは、1つのリクエストが終わる場所と次のリクエストが始まる場所を判断する必要がある。
HTTP request smugglingが起こったとき
攻撃者はフロントエンドリクエストの一部をバックエンドサーバーによって次のリクエストの開始として解釈させる。これにより、前のリクエストの終わりの部分が次のリクエストの前に追加されるため、アプリケーションがリクエストを処理する際に干渉が起きてしまう。
攻撃の実行方法
HTTP/1仕様では、リクエストの終端を指定するためにContent-LengthヘッダーとTransfer-Encodingヘッダーの2つの異なる方法が提供されている。
・Content-Lengthヘッダー
→メッセージ本体の長さをバイト数で指定
・Transfer-Encodingヘッダー
→メッセージ本体がチャンクエンコーディングを使用していることを指定
Content-LengthヘッダーとTransfer-Encodingヘッダーの両方を単一のHTTP/1リクエストに配置し、これらを操作してフロントエンドとバックエンドサーバーがリクエストを異なる方法で処理するようにさせる
引き起こされる脆弱性の例
1.CL.TE vulnerabilities
フロントエンドサーバー: Content-Lengthヘッダー(CL)の形で
バックエンドサーバー: Transfer-Encodingヘッダー(TL)の形であるとき
例
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked
0
security
~
フロントエンドサーバーはCLを処理し、リクエスト本体が13バイトの長さであると判断する。このリクエストはバックエンドサーバーに転送される。
バックエンドサーバーはTEを処理し、メッセージ本体をチャンク化されたエンコーディングで使用しているとみなす。"0"によってチャンクのサイズが0であることが示されているため、これ以上データがないと判断されてしまうため、それ以降の内容が上記のものに関係がないとみなされてしまう。
2.TE.CL vulnerabilities
フロントエンドサーバー:TE
バックエンドサーバー: CL
例
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
security
0
フロントエンドサーバーはTEを処理し、メッセージ本体をチャンク化されたエンコーディングで使用しているとみなす。8バイトの長さであると宣言された最初のチャンクを"security"に続く行の開始まで処理する。次に長さが0であると宣言された二番目のチャンクを処理しこれをリクエストの終了としてバックエンドサーバーに転送する。
バックエンドサーバーはCLを処理し、リクエスト本体が"8"に続く行の開始までの3バイトの長さであると判断する。その後に続く"security"で始まるバイトは処理されず、バックエンドサーバーはこれらをシーケンス内の次のリクエストの開始として扱う。
3.TEの難読化
フロントエンドサーバー、バックエンドサーバーともにTEをポートしているが、ヘッダーが何らかの方法で隠蔽されることによって、どちらかのサーバーがそれらを処理しなくなる
例
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
HTTP request smugglingの特定方法
1.CL.TE脆弱性の特定方法
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4
1
A
X
上記のようなリクエストを送信することによって、フロントエンドサーバーはCLを使用しリクエストボディの最初の4バイト(1\nA\n)のみをリクエストの終わりとみなし、'X'は省略されるためバックエンドサーバーには送信されない。
対して、バックエンドサーバーはTEを利用して最初のチャンクを'1\nA\n'と処理し、次のチャンクを待ち続けるため、遅延が発生する。これにより脆弱性を発見することができる。
2.TE.CL脆弱性の特定方法
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6
0
X
上記のようなリクエストを送信することで、フロントエンドサーバーはTEを使用し、'X'を省略したうえでこのリクエストの一部のみを転送するが、
バックエンドサーバーはCLを使用し、メッセージ本文にさらに多くのコンテンツが含まれることを期待して、残りのコンテンツが到着するのを待機するため、遅延が発生することで脆弱性を発見することができる。
終わりに
いろんなサイトを見て学んだことを自分なりにまとめた。
まだまだ書き足りていないことがあるので、随時更新したい。
言語化してまとめることで理解が深まったと思うので良かった。
参考文献
https://portswigger.net/web-security/request-smuggling
https://portswigger.net/web-security/request-smuggling/finding
https://yamory.io/blog/about-http-request-smuggling/
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Length
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Transfer-Encoding