-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ヒント #1
Comments
ヒント追加です!起動したときに出る Go のバージョン 1.16.4 に注目してください! |
Go で HTTPリクエストヘッダは次のようにして送ることができます。サンプルコード https://github.com/kanmu/gocon-2021-autumn/blob/main/http_client_example/client.go を使う場合次のようになります。またヘッダはいくつも送ることができます。 req, err := http.NewRequest("GET", "http://localhost:8000/flag.txt", nil)
if err != nil {
log.Fatal(err)
}
// リクエストヘッダを送る
req.Header.Add("Header1", "Value1")
req.Header.Add("Header2", "Value2") |
ところでGo 1.16.5 のリリースノートを見てみましょう。Go 1.16.4 で見つかったいくつかセキュリティ issue が修正されていますね? |
Go 1.16.4 には次のような Issue が立てられていたようです。 そして次のコミットで問題が修正されています。 この問題は CVE-2021-33197 として登録されている脆弱性です。Connection ヘッダは 先ほどのコミットのテストコードのこのあたりが参考になりそうです。これを利用すると X-Forwarded-For が1つ消せるかも? golang/go@0410005#diff-94fbfd2113a685abada242cd95e27e61f8577413f03f50c10606cd018d90ccadR273-R276 |
ヒント
リバースプロキシや X-Forwarded-For、出題されたアプリケーションの説明を書きますので参考にしてみてください。ある程度時間が経過したらこちらの issue のコメント欄に徐々にヒントを投下していきます。この概要欄が最初のヒントになります。
アプリケーションの説明
docker run で HTTP Server を起動すると Front Proxy, Middle Proxy, Backend 3つの HTTP サーバが起動 します。Front Proxy は 127.0.0.1:8000 で接続を待ち受け、HTTP リクエストを受信するとその内容をそのまま Middle Proxy に転送 (
httputil.NewSingleHostReverseProxy(murl).ServeHTTP(w, r)
) します。Middle Proxy は 127.0.0.1:<※ランダムなポート> で接続を待ち受け、HTTP リクエストを受信するとその内容をそのまま Backend に転送 (httputil.NewSingleHostReverseProxy(burl).ServeHTTP(w, r)
)します。Backend は 127.0.0.1:<※ランダム なポート> で接続を待ち受け、HTTP リクエストを受信すると、 X-Forwarded-For という HTTP ヘッダをカンマ区切りで分割し、先頭のものを Source IP とみなします。ここで Source IP が 127.0.0.1 であれば flag.txt へのアクセスができます。※ Backend および Middle Proxy は
httptest.NewServer
で起動しています。httptest.NewServer
はランダムなポートで起動します。HTTPリクエストの流れ
このアプリケーションに HTTP リクエストを投げてからどのように HTTP リクエストが Backend まで渡るかを追ってみます。
まず試しに、docker run してから http_client_example にあるサンプルで HTTP リクエストを送信してみます。Front Proxy, Middle Proxy, Backend が受信する HTTP リクエストのダンプが表示されます。加えて r.RemoteAddr の内容も表示されます。そのダンプの内容およびそれを図で表すと次のようになります(IPやポートは環境によって変わります)。
ダンプ
図
本問題を解くために重要となる r.RemoteAddr と X-Forwarded-For の動きを追ってみます。
まず Client (あなた)が HTTP リクエストを送信すると、r.RemoteAddr = 172.17.0.1 として Front Proxy に到達します。 r.RemoteAddr にはリクエストを送信したコンポーネントのIPが入ります。
続いて Front Proxy は Middle Proxy に HTTP リクエストを転送するのですが、Client から送られてきた r.RemoteAddr を X-Forwarded-For に入れて Middle Proxy に転送します。これにより、Middle Proxy は r.RemoteAddr = 127.0.0.1 (Front Proxy の IP), X-Forwarded-For = 172.17.0.1 (Client の IP) と してリクエストを受け取ります。
Middle Proxy は Front Proxy と同様、前段である Front Proxy の r.RemoteAddr を X-Forwarded-For に入れてから Backend に転送します。
このように、直前のコンポーネントの IP は X-Forwarded-For に入れて転送されるため、多段構成になっていたとしても、X-Forwarded-For をたどることで大本の送信元IPを知ることができます。
本問題の関門はどこなのか?
ここで本問題なのですが、Backend は X-Forwarded-For の先頭を取り出して、それが 127.0.0.1 であれば flag.txt へのアクセスを許可しています。しかしながらこの図の通り、X-Forwarded-For の先頭には大本のリクエスト送信元である Client の IP 入っています。Client の IP は 127.0.0.1 ではないため flag.txt にアクセスできません。どうにかして送信元IPを 127.0.0.1 として Backend に到達させる必要があります。
最初のヒント
コードの中から脆弱性を探しましょう。そしてその脆弱性は問題のコードの中だけに潜んでいるとは限りません。使われている Go のバージョンは 1.16.4 です。
The text was updated successfully, but these errors were encountered: