サーバーサイドリクエストフォージェリー (SSRF)
サーバーサイドリクエストフォージェリー (SSRF) とは、攻撃者が任意の宛先に対してネットワークリクエストを送信できるようにする脆弱性です。SSRF では、これらのリクエストがサーバー内部から発信されるため、通常、外部のクライアントよりも広範なアクセス権限を持つことになります。
これにより、攻撃者が機密リソースにアクセスしたり、その他の不正な操作を行ったりする可能性があります。
シナリオ例
アプリケーションに、指定された URL から画像を取得するエンドポイントがあるとします。
GET /fetch-image?url=https://example.com/image.png
このサーバーは、社内のイントラネットにアクセスできます。
サーバーが指定された URL 引数を検証しなかった場合、クライアントは API にイントラネットの URL を渡すことで、機密データを抽出できてしまいます。
fetch("https://example.org/fetch-image?url=http://localhost:443/admin/org.png");
クライアントは http://localhost:443/ に直接アクセスすることはできませんが、サーバーはアクセス可能であり、サーバーがレスポンスをクライアントに中継します。
クライアントは HTTP リクエストを行う必要はありません。file:// プロトコルを使用できる場合があります。
fetch("https://example.org/fetch-image?url=file:///etc/passwd");
このような場合、攻撃者は機密データにアクセスできてしまう可能性があります。攻撃者がレスポンス本文を取得できない場合もありますが、その場合でも問題を引き起こす可能性があります。
- サーバーに多数のリクエストを送信させることで、攻撃者はサービス拒否攻撃 (DoS) を実行することができます。
- サーバーから返されるステータスコードや、リクエストの実行にかかる時間を分析することで、攻撃者は標的に関する機密情報を推測できる可能性があります。
攻撃者は、検証を回避するためにリダイレクトやリダイレクトチェーンを利用する可能性があります。例えば、攻撃者が https://evilexample.org/redirect というドメインを所有しており、そのホストが http://localhost:443/ やその他の(内部)URL へリダイレクトするだけの場合、入力検証を迂回できる可能性があります。
fetch("https://example.org/fetch-image?url=https://evilexample.org/redirect");
SSRF に対する防御
SSRF の脆弱性を軽減するには、入力の検証、慎重なレスポンス処理、および安全なネットワークアーキテクチャを組み合わせた複数の防御戦略が必要です。主な対策としては、次のようなものがあります。
入力の検証と許可リスト
サーバー API が使用する URL を制限します。たとえば、前述の fetch-image サービスでは、想定されるドメインを含む許可リストを指定することができます。
const ALLOWED_DOMAINS = ["https://api.example.com", "https://cdn.example.com"];
プロトコルと URL スキームのブロック
特定の URL スキームのみを許可するようにしてください。一般的なウェブアプリケーションの場合、https:// のみを許可すれば十分でしょう。
リダイレクト検証
リダイレクトを自動的に追跡せず、リダイレクト先の URL に対して入力検証や許可リストを適用してください。リダイレクトの連鎖を制限してください。
最小限の権限と分離
対外リクエストを行うサービスが、必要以上の権限で実行されないようにし、リクエスト機能を持つサービスと機密性の高い内部サービスを同じ場所に配置しないようにしてください。
防御概要チェックリスト
- リソースを取得したり、ユーザー入力の検証や許可リスト登録を行うすべての機能を点検しましょう。
- HTTPS 以外のすべてのプロトコルをブロックしましょう。
- URL のリダイレクトに注意し、リダイレクトの連鎖を制限しましょう。
- サーバーのネットワーク権限については「最小権限の原則」を適用しましょう。理想的には、必要な場合を除き、サーバーが内部ネットワークに無制限にアクセスできないようにすべきです。
- リクエストをログに記録し、監視しましょう。