Server-Side Request Forgery
略称: SSRF
サーバーが外部に公開していないサーバーにリクエストを送信してしまう脆弱性のこと
攻撃者が応答が閲覧できる場合、情報漏洩につながる
場合によってはAPIリクエストやコマンド発行を行うことで様々な悪用ができる
例
code:server.py
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.get("/proxy")
def proxy():
url = request.args.get("url", "http://example.com/")
text = requests.get(url).text
return jsonify({"response": text})
@app.get("/flag")
def get_flag():
if request.remote_addr != "127.0.0.1":
return "ローカルからしか閲覧できません!"
return "SECRET_FLAG"
if __name__ == "__main__":
app.run(debug=True)
http://server.example.com/でサーバーが動いているとする
/proxy?url=http://hogehoge.example.com/でhttp://hogehoge.example.com/の内容を取得できる
ユーザーが入力したURLを検証せずにそのままリクエストを送信していることに注目する
/flagにアクセスするとフラグが貰えるが、内部(127.0.0.1)からしか閲覧できない
これを取得することを考える
/proxy?url=http://server.example.com/flagにアクセスしてみる
/proxyの処理でhttp://server.example.com/flagにリクエストが送信される
内部からリクエストを送っているため、送信元IPは127.0.0.1になる
/flagは127.0.0.1からのリクエストが来たので、フラグを返す
/proxyが/flagのレスポンスをそのまま返す
結果的に/flagの内容を外部から取得できた!
対策
そもそもそんな機能作るな
SSRFは非常に複雑なので対策が難しい
ホワイトリストで検証する
a.example.com, b.example.comとしか通信しないことが想定されているなら、a.example.com,b.example.com以外のドメインを指すURLを弾けばいい
文字列処理も自分でせずに標準のパーサーを利用するとよい
ツール
Gopherus https://github.com/tarunkant/Gopherus
gopher://プロトコルのexploitを自動生成してくれる
テクニック
Filter bypass
127.0.0.1や0.0.0.0が禁止されていても、IPの表現方法は多数ある
http://localhost/
http://127.1/
n進数
127.0.0.1 http://2130706433/ http://017700000001/ http://0x7F000001/
0.0.0.0 http://0/
ipv6
127.0.0.1 http://[0:0:0:0:0:ffff:127.0.0.1]/
0.0.0.0 http://[::]/
DNS http://localtest.me/ http://127.0.0.1.nip.io/
X.X.X.X.nip.ioを解決するとX.X.X.Xが返ってくる
ライブラリによっては正規化が刺さる
example。com, ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜなど
先頭だけチェックしてる場合
http://example.com@127.0.0.1/ → 127.0.0.1
http://example.com.attacker.domain/
Bypassまとめ https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery#bypassing-filters
URLパーサの挙動の差異の悪用
Orange TsaiさんがBlackHatで発表した手法
https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf
Pythonのurllib2でURLを検証してリクエストはrequestsで送るような場合、ふたつのライブラリのURLの解釈の違いを利用することで検証をbypassできる
現在でも使えるかは未検証
Python以外でも原理的に悪用できる可能性がある
@を使ったURL検証のバイパスはいろんなところで見る
リダイレクトによる制限の回避
攻撃者のサーバーを指定できるとき、304などで好きなURLにリダイレクトさせる
プロトコルの変更にも使える
curlではhttp, https, ftp, ftpsしかリダイレクトに使えない https://github.com/curl/curl/blob/master/lib/url.c#L581
プロトコル
gopher://
任意のデータを任意の送信先に送信することができる最強のプロトコル
gopher://{ip}:{port}/x{payload}で送信できる
URL Encodeすればバイナリも送れる
最近のバージョンのcurlはで%00が使えなくなった。NULLを含まないバイナリなら送れる
curl (libcurl)くらいしか対応してない
file://
対応している場合、Local File Inclusionに繋がる
Denoのfetchは対応している
CrewCTF 2023 - safe_proxy
ftp://
FTP Bounce Attack
PORTコマンドを利用してファイルの送信先を任意のIP/portにする攻撃
ほとんどのFTPソフトウェアでは対策されているが、対策されていないnodeftpdがCTFではよく使われるっぽい
https://github.com/nodeftpd/nodeftpd
https://graneed.hatenablog.com/entry/2021/08/09/115452#FTPのPASVモードを使用した任意ポートへのバイナリデータ送信
DNS Rebinding
DNS応答のTTLを極めて短くすることで、ドメインのIPチェックを回避する攻撃
入力されたドメインのIPがY.Y.Y.Yだったら弾くようなプログラムがあるとき
攻撃者が持つevil.example.comを入力する
チェック時にはevil.example.comをX.X.X.Xとして解決させる
このときにTTLを極めて短くすることで、次の通信時にドメインの再解決を行わせる
実際に使用するときに再解決が起きる
このときはevil.example.comをY.Y.Y.Yとして解決させる
これでチェックをbypassできた
DNSにおける一種のTOCTOUといえる
DNSリバインディング(DNS Rebinding)対策総まとめ https://blog.tokumaru.org/2022/05/dns-rebinding-protection.html
TLS Poison https://github.com/jmdx/TLS-poison
TLSの仕様を利用した攻撃手法
攻撃者のサーバーにhttpsなどのTLS通信ができる場合に使用できる
セッションIDを利用して任意のサーバーに任意の短いデータを送信することができる
ブラウザからのSSRF
CSRFで内部IPにPOST
Content Security Policy report-uri
WebRTC
ターゲット
Redis
通信の暗号化や認証がされていない場合、SSRFでRedisコマンドを発行できる
Exploiting Redis Through SSRF Attack https://infosecwriteups.com/exploiting-redis-through-ssrf-attack-be625682461b
記事にもあるように、RedisはHTTPによるSSRFの対策をしている
環境によってはRemote Code Executionができたりする
RedisからOSコマンドを実行する攻撃方法(SLAVEOF編) https://knqyf263.hatenablog.com/entry/2019/07/16/092907
現在でも使えるかは要検証
Memcached
Redisと同様にSSRFのターゲットになる
DevTools API
--remote-debugging-port=<port>をつけて起動したChromeはデバッグ用のportを開く
Chrome DevTools Protocol https://chromedevtools.github.io/devtools-protocol/
Pupeteerはこれを利用してChromeを操作している
SSRFでこのportにアクセスすることで色々な悪用ができる
https://graneed.hatenablog.com/entry/2022/09/28/100000#ChromeのDevToolsのデバッグポートに対するSSRF
corCTF 2021 - saasme https://larry.science/post/corctf-2021/#saasme-2-solves
ASIS CTF 2022 Quals - xtr https://nanimokangaeteinai.hateblo.jp/entry/2022/10/16/164405 (SSRFではないが)
クラウド
AWSなどのクラウドサービスでは内部IPにアクセスすることで機密情報を見れることがある
SSRFを利用してクラウドの機密情報を漏洩させることができる
まとめるの面倒なのでHackTricks見てください
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery#ssrf-url-for-cloud-instances
他にも色々
内部にサーバーがある限りSSRFで悪用できる可能性がある
資料
HackTricks https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery