Help us understand the problem. What is going on with this article?

HTTP Request Smuggling を理解する

はじめに

ISC2年、IPFactory所属のsh0です。
これは、portswiggerのHTTP Request Smugglingの記事を参考に自分なりの理解を書いたものです。(ほぼ翻訳)

この記事を読むにあたって必要な知識
  • Transfer-Encoding: chunked

リクエストとレスポンスのデータのエンコーディングを指定するヘッダー

事前に全体のレスポンスのバイト数が分からない場合に、chunk(塊)毎に16進数でバイト数を記して、最後に0のみからなる行と空行を示してレスポンスを返す。(\r\nはバイト数にカウントされない
スクリーンショット 2019-12-16 18.11.38.png

  • Content-Length: バイト数
    • リクエスト or レスポンスのデータのバイト数を指定するヘッダー
    • 改行(\r\n)もバイト数に含まれる

以下のContent-Lengthは5

a


  • POSTパラメータの改行

以下のように改行してもパラメータxの値と見なされる。

スクリーンショット 2019-12-17 15.30.38.png

HTTP Request Smuggling(HRS)とは

フロントエンドサーバー(リバースプロキシ、ロードバランサーなど)とバックエンドサーバーでリクエストの終端の解釈が異なる場合に発生する脆弱性

CL.TE vulnerabilities

例えば、フロントエンドがContent-Length(以下CL)のみに対応していて、バックエンドがTransfer-Encoding(以下TE)にのみ対応していた場合のリクエストの処理の流れを見ていく。
スクリーンショット 2019-12-16 14.03.09.png

まず、CLに対応しているフロントエンドがContent-Lengthに従い9バイト(0\r\n\r\nHACK)までを処理してバックエンドに転送する。
TEに対応しているバックエンドはTransfer-Encoding: chunkedに従い0を受け取った時点でリクエストの終了と判断してHACKは次のリクエストの開始として扱う。このように、フロントエンドがCLでバックエンドがTEの形をCL.TE vulnerabilitiesと呼ぶ
これを利用すると、攻撃者は次のユーザーのリクエストの開始時に任意のコンテンツを追加することができる。

TE.CL vulnerabilities

次に、フロントエンドがTEでバックエンドがCLのパターンを以下のリクエストを例に見ていく。
スクリーンショット 2019-12-21 16.56.23.png
まず、フロントエンドがTransfer-Encoding: chunkedに従い、4〜0まで処理してバックエンドに転送する。
バックエンドは、Content-Length: 3に従い、4\r\nまで処理するため、HACK\r\n0\r\nは次のリクエストに回される。

TEの難読化

フロントエンドとバックエンドの両方がTransfer-Encodingをサポートしている場合に、ヘッダーを難読化することで、どちらか一方にだけ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

CL.TE vulnerabilitiesの見つけ方①

CL.TE vulnerabilitiesのあるアプリケーションに対して、以下のリクエストを送るとレスポンスが遅延する。
スクリーンショット 2019-12-16 15.55.59.png
なぜなら、フロントエンドが、Content-Length: 4に従い1\r\nAまでを処理してバックエンドに転送する。
それを受け取ったバックエンドは、Transfer-Encoding:chunkedに従い処理するが、0がないため次のchunkがくるものだと解釈し一定時間待つため遅延が発生する。

CL.TE vulnerabilitiesの見つけ方その②

CL.TE vulnerabilitiesのあるアプリケーションに対して、以下のリクエストを送ったとする。
スクリーンショット 2019-12-16 17.47.18.png
まず、フロントエンドがContent-Length: 38に従い、0からDummy-Header:まで処理してバックエンドに転送する。
バックエンドは、Transfer-Encoding: chunkedに従い処理するため、GET /hack HTTP/1.1\r\nDummy-Header:がバックエンドに残る。
次に、以下のようなリクエストを送ると、
スクリーンショット 2019-12-21 17.10.45.png
バックエンドに残存していたデータがリクエストの先頭に付加されるため、結果的に以下のようなリクエストになる。
スクリーンショット 2019-12-21 17.10.36.png
/にアクセスしたはずが、HRSにより、/hackという存在しないパスにリクエストを送っているため
Not Foundが返ってきて、脆弱性があると判断する事ができる。

TE.CL vulnerabilitiesの見つけ方その①

TE.CL vulnerabilitiesのあるアプリケーションに対して、以下のリクエストを送るとレスポンスが遅延する。
スクリーンショット 2019-12-16 16.11.42.png
なぜなら、フロントエンドが、Transfer-Encoding: chunkedに従い0をバックエンドに転送する。
それを受け取ったバックエンドは、Content-Length: 6に従い、残りのデータがくるのを待つため、遅延が発生する。

TE.CL vulnerabilitiesの見つけ方その②

TE.CL vulnerabilitiesのあるアプリケーションに対して、以下のリクエストを送ったとする。
スクリーンショット 2019-12-17 15.50.15.png
まず、フロントエンドがTransfer-Encoding: chunkedに従い、7cから0\r\nまで処理してバックエンドに転送する。
バックエンドは、Content-Length: 4に従い、7c\r\nまで処理するため、GET /404 HTTP/1.1以降がバックエンドに残る。
次に、以下のようなリクエストを送ると
スクリーンショット 2019-12-21 17.24.17.png
残存していたGET /404 HTTP/1.1がリクエストの先頭に付加されて結果的に以下のようなリクエストになる。(x=以降は全てxの値と見なされる)
スクリーンショット 2019-12-21 17.25.53.png
/にアクセスしたはずが、HRSにより、/404という存在しないパスにリクエストを送っているため
Not Foundが返ってきて、HRSが成功している事がわかる。

HRSによるフロントエンドのセキュリティバイパス

フロントエンドサーバでしかアクセス制御を実装していない場合、HRSを利用すればバイパスすることができる。
例えば、CL.TE vulnerabilitiesのあるアプリケーションで/adminへのアクセスがフロントエンドで禁止されていて、尚且つ、localhostからしかアクセスできない場合
以下のようなリクエストを送ればそれらをバイパスすることができる。
スクリーンショット 2019-12-18 21.33.38.png
まず、フロントエンドがContent-Length: 47に従って、0\r\nからx=までをバックエンドに転送する。
バックエンドは、Transfer-Encoding:chunkedに従って処理するため、GET /admin HTTP/1.1からx=までがバックエンドに残る。
再度同じリクエストを送ると、バックエンドに残存していたデータがリクエストの先頭に付加されて以下のようなリクエストになるため、/adminにアクセスすることができる。
スクリーンショット 2019-12-18 21.39.52.png

フロントエンドによるヘッダーの付加

フロントエンドがバックエンドにリクエストを転送する際に、ヘッダーを付加することがある。(XFFなど)
そのようなアプリケーションにHRSをした時に、フロントエンドが通常付加するヘッダーがないために、バックエンドが正常にリクエストを処理できず、意図した挙動にならない事がある。
しかし、以下のように入力値をレスポンスに反映するような機能がある場合、この付加されるヘッダーをレスポンスに含める事ができる。
スクリーンショット 2019-12-21 10.46.39.png

このアプリケーションがCL.TE vulnerabilitiesがある場合以下のようなリクエストを送ると
スクリーンショット 2019-12-21 10.54.49.png

フロントエンドがContent-Length: 51に従い、0からsearch=までを処理して何らかのヘッダーを付加してバックエンドに転送する。
バックエンドは、Transfer-Encoding: chunkedに従って処理するため、POST / HTTP/1.1からsearch=までがバックエンドに残る。
もう一度リクエストを送ると、フロントエンドがヘッダーを付加してバックエンドに転送し、バックエンドに残存していたデータがリクエストの先頭に付加されて以下のようなリクエストになるため、ヘッダーが画面に出力される。
スクリーンショット 2019-12-21 10.56.45.png

他のユーザーのリクエストを取得する

掲示板のような、ユーザの入力値を保存する事ができる機能がある場合、他のユーザーのリクエストを取得する事ができる。

例えば、CL.TE vulnerabilitiesのあるアプリケーションで
以下のようにcommentパラメータに指定した値が保存される機能がある場合
スクリーンショット 2019-12-21 11.31.03.png

以下のようなリクエストを送ると
スクリーンショット 2019-12-21 11.25.04.png
フロントエンドが、Content-Length: 284に従い0からcomment=までをバックエンドに転送する。
バックエンドは、Transfer-Encoding: chunkedにより、POST /post/comment HTTP/1.1からcomment=までがバックエンドに残る。
この状態で、他のユーザーが何らかのリクエストを送った場合、先ほどのリクエストのcommentパラメータの値として解釈されるため、他のユーザーのリクエストを取得する事ができる。

熱が出たので続きは後日...

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした