この記事はCTFのWebセキュリティ Advent Calendar 2021の2日目の記事です。
本まとめはWebセキュリティで共通して使えますが、セキュリティコンテスト(CTF)で使うためのまとめです。
悪用しないこと。勝手に普通のサーバで試行すると犯罪です。
HTTP
- どこを見て学習してもいいのだが、MDNを参照するのが一番オススメ
- HTTP の基本 - HTTP | MDN
- 難しめに書いてあるので、他のもう少し優しく書いてあるもので勉強してから、辞書的に戻ってきてもいいかも
- HTTPメソッド
- たまにGETで取得しているのをPOSTにしてみたりPUTにしてみるとフラグが出たりする(大体、メソッドを変えてみてね見たいな誘導が問題中にある)
- Software Security | HTTP Verb Tampering
- メソッド込みでブラックリスト作ってても、注意しないと意外な所から呼ばれてbypassされるかも
- HTTPステータス番号
- あまりCTFでは問題になってこないが、読めるようになると色々把握しやすい
- Content-Type (MIME Type)
- エンコードについて
- GETパラメタの中身とか、BODY部分ではURLエンコーディングされている場合がある
- 空白を%20とするか+にするかで使い分けされているので注意
- テク
- GETパラメタ
- HTTP parameter pollution
- Client-side HTTP parameter pollution - 妄想まとめ
- 同名のパラメタがあった場合の処理の仕方が色々異なる
- ASP.NETでは同名があったら結合するので、これを利用したWAFのbypassが可能
- HTTP Parameter Pollution | Imperva
- ここに微妙にまとまっている https://miro.medium.com/max/2400/1*POs4sP0fQVlPvTH9vw1U-A.jpeg
- GETパラメタの配列化
- HTTP parameter pollution
HTTPのHeaderまとめ
- Referer: https://www.google.com
- 直前のページのURL
- X-Forwarded-For: 123.123.123.123
- 送信IPを偽装したいときに使用
- PHPなら
$headers = apache_request_headers(); $ip = $headers[‘X-Forwarded-For’];
で取ってくる - 元々はプロキシサーバ経由でも元々のIPを特定できるようにしたもの X-Forwarded-For - HTTP | MDN
- remote_addrとかx-forwarded-forとかx-real-ipとか - Carpe Diem
- CTFtime.org / ångstromCTF 2021 / Spoofy
- heroku上に構成されたサイトで、
X-Forwarded-For
を使って1.3.3.7経由であるかを確認している - Flask apps on Heroku susceptible to IP spoofing
client --> cloudflare --> heroku --> app
となっていたらX-Forwarding-For: client.ip.addr, cloudflare.ip.addr
- herokuは追加しないと?と思ったが、問題ではくっついているように見える。分かってない
- The tale of Clojure, Heroku and X-Forwarded-For – Igor Bondarenko
- こういう場合でもX-Forwarded-Forを複数つければbypass可能
curl https://actf-spoofy.herokuapp.com/ -H "X-Forwarded-For: 1.3.3.7" -H "X-Forwarded-For: , 1.3.3.7"
curl https://actf-spoofy.herokuapp.com/ -H X-Forwarded-For: 1.3.3.7" -H "X-Forwarded-For: <random_ip>, 1.3.3.7"
- heroku上に構成されたサイトで、
- 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?
- Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
- preloadにしたURLがChromiumに送られてリスト化されているけど、ステージング環境とかがここに入ってこない?その辺大丈夫?
- ステージング時は気を付けるべきでは?
- Feature-Policy: fullscreen 'self'
- Feature PolicyおよびFeature unsized-mediaの導入ガイド - 銀色うつ時間
- とても分かりやすい。なるほど。
- フルスクリーンを抑制できるっぽいが、セキュリティ的なうまみがあるんだろうか
- ぱっと考えてみると、バナー広告とかが攻撃者に乗っ取られてフルスクリーンを強制するとか?
- いい記事も、いい攻撃例も思いつかないが、脅しには使えそうな感じはする
- 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固定でいいんじゃないかな?
- このレスポンスのページをframeの内部で表示することができるかを指定する
- X-XSS-Protection: 1; mode=block
- ブラウザのXSS防御機構を呼び出すもの
- X-XSS-Protection - HTTP | MDN
- 正直ブラウザ側が放棄したヘッダーを使うのは少し怖い気がする
- メンテが終わった機能を使い続けてしまう恐れ
- 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
- Cross-Origin-Opener-Policyについて - ASnoKaze blog
- openerについての制約用ヘッダー
- 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 okDNT: 1
track ngDNT: 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
- HTTP Request Smuggling を理解する - Qiita
- HTTP Desync攻撃
- HTTP Request Smuggling を理解する - Qiita
- Black Hat USA 2019: 今注目すべき Web セキュリティ関連トピックの解説 - Flatt Security Blog
- Transfer-Encoding - HTTP | MDN
- ここを見ると、Transfer-Encoding: chunkedが認識されたら、Content-Lengthは省略されるらしい
- HAProxyとgunicornの組合せは、TE-CL攻撃ができる
- Smuggler - An HTTP Request Smuggling / Desync Testing Tool — SkyNet Tools
- 発展形なんかな?
- 問題
- 403 Forbidden bypass
- https://twitter.com/intigriti/status/1222868788070227970?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1222868788070227970%7Ctwgr%5E&ref_url=https%3A%2F%2Fwww.redditmedia.com%2Fmediaembed%2Few5k2w%3Fresponsive%3Dtrueis_nightmode%3Dfalse
http://example.com/./hidden.html
はhttp://example.com/hidden.html
として解釈される/hidden.html
が403になるような設定になっていれば、こうすれば/./hidden.html
となってバイパスできる
- X-HTTP-Method-Override
- CTFtime.org / Square CTF 2020 / Barrel Roll
- 例えば、GOでリバースプロキシを書いて、rubyでフロントエンドを書いているとする
- GOで
r.PathPrefix("/contents/FLAG").Methods("GET").HandlerFunc(func(w http.ResponseWriter, req *http.Request) { http.Error(w, "Forbidden", 403) })
みたいな感じ curl -X POST -H "X-HTTP-Method-Override: GET" http://localhost:8090/contents/FLAG
でフラグが取得できる- これはGOではPOSTリクエストとして解釈されるが、ruby側ではX-HTTP-Method-Overrideを考慮してGETリクエストとして解釈されるためである
- How to exploit parser differentials | GitLabが元ネタ
- ちなみに
curl -X POST -d "_method=GET" http://localhost:8090/contents/FLAG
でも同様に突破できる - ここみたいな感じに任意のHTTPメソッドを指定できる。どの標準なのかは分からないが、いろんなライブラリでそういうことになってるっぽいのでデファクトスタンダード的なやつかも(まったくわかってない)
- CTFtime.org / Square CTF 2020 / Barrel Roll
- HTTP Request Smuggling over HTTP/2 Cleartext (h2c)
- PoC: GitHub - BishopFox/h2csmuggler: HTTP Request Smuggling over HTTP/2 Cleartext (h2c)
- writeups/2020/Boot2root_ctf/Smuggle at master · Red-Knights-CTF/writeups · GitHub
- これで攻撃が完了したというWriteupもある
pyhton3 h2csumuggler.py -x https://192.34.57.73:8001/ https://192.34.57.73:8001/flag
で/flagが400errorでアク禁かかっていても情報を抜き出せている- READMEにある画像を見ていると、なんとなくどういうことかが分かる
- トンネルが貼られてreverse proxyを無視した通信をしてしまうから、アク禁をバイパスできるっぽい
- これもRequest Smugglingの1つ?
- GitHub - neex/http2smugl
- H2C Smuggling in the Wild – Assetnote
- PoC: GitHub - BishopFox/h2csmuggler: HTTP Request Smuggling over HTTP/2 Cleartext (h2c)
- CL-TEタイプ
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でアクセス制限をかけていてもバイパスできる
- TE-TEタイプ
- #1002188 Potential HTTP Request Smuggling in nodejs
- revproxyとしてhaproxy、webサーバとしてnodejs
- #1002188 Potential HTTP Request Smuggling in nodejs
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レスポンスの構造を改変可能な状態になっていると、できることの1つ
- 通称としてはHTTP Response Splittingという名前になっているが、自由にHTTPレスポンスが構築できるということなので、XSSとかキャッシュ汚染とかが可能
- 参考
- バグバウンティのレポートではヘッダーインジェクションからできる攻撃としてHTTP Response Splittingで出来る攻撃が紹介されていることが多い印象
HTTP/2
- GoogleのHTTP/2 and SPDY indicatorという拡張機能を入れると、HTTP2で接続されているかが分かる。ちなみにBurp Suiteなどでプロキシを挟んでいると、HTTP2にならない場合があるので注意。
- HTTP Request Smuggling over HTTP/2 Cleartext (h2c)
- PoC: GitHub - BishopFox/h2csmuggler: HTTP Request Smuggling over HTTP/2 Cleartext (h2c)
- writeups/2020/Boot2root_ctf/Smuggle at master · Red-Knights-CTF/writeups · GitHub
- これで攻撃が完了したというWriteupもある
pyhton3 h2csumuggler.py -x https://192.34.57.73:8001/ https://192.34.57.73:8001/flag
で/flagが400errorでアク禁かかっていても情報を抜き出せている- READMEにある画像を見ていると、なんとなくどういうことかが分かる
- トンネルが貼られてreverse proxyを無視した通信をしてしまうから、アク禁をバイパスできるっぽい
- これもRequest Smugglingの1つ?
- GitHub - neex/http2smugl
- H2C Smuggling in the Wild – Assetnote
- 問題
- PoC: GitHub - BishopFox/h2csmuggler: HTTP Request Smuggling over HTTP/2 Cleartext (h2c)