WebVulnerabilities

SSRF攻撃について

概要

SSRF(Server-Side Request Forgery、サーバーサイドリクエストフォージェリ)攻撃は、攻撃者がサーバー側のリクエストを不正に操作して、意図しない外部または内部リソースへのリクエストを発生させる攻撃手法です。これにより、攻撃者は通常アクセスできない内部ネットワークや、保護されたリソースにアクセスできるようになる可能性があります。SSRF攻撃は、Webアプリケーションがユーザーからの入力に基づいてHTTPリクエストを生成する際に発生することが多く、データの漏洩や内部システムのスキャンに悪用されます。


脆弱性を持つコードの例と攻撃手法

PHP

脆弱なコード:

<?php
$url = $_GET['url'];
$response = file_get_contents($url);
echo $response;
?>

攻撃手法: 攻撃者がurlパラメータにhttp://localhost/adminのような内部URLを指定することで、内部ネットワーク上のサービスにアクセスできます。また、file://スキームを利用してサーバー上のローカルファイルを読み取ることも可能です。

Python

脆弱なコード:

from flask import Flask, request
import requests

app = Flask(__name__)

@app.route('/fetch')
def fetch():
    url = request.args.get('url')
    response = requests.get(url)
    return response.content

if __name__ == '__main__':
    app.run()

攻撃手法: 攻撃者がurlパラメータにhttp://169.254.169.254/latest/meta-data/のようなAWSのメタデータサービスへのリクエストを送信すると、クラウドインスタンスに関する機密情報が漏洩する可能性があります。

Node.js

脆弱なコード:

const express = require('express');
const axios = require('axios');
const app = express();

app.get('/fetch', async (req, res) => {
    const url = req.query.url;
    const response = await axios.get(url);
    res.send(response.data);
});

app.listen(3000);

攻撃手法: 攻撃者がurlパラメータに内部IPアドレスを指定することで、内部ネットワーク上のサービスやAPIにアクセスできるようになります。

Java

脆弱なコード:

import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SSRFServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String url = request.getParameter("url");
        URL obj = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String inputLine;
        StringBuffer content = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            content.append(inputLine);
        }
        in.close();
        response.getWriter().println(content.toString());
    }
}

攻撃手法: 攻撃者がurlパラメータに内部ネットワーク上のサービスURLを指定することで、内部リソースに対する情報を取得したり、リクエストを送信することができます。


防止策

  1. ユーザー入力の検証とサニタイズ:
    • URLパラメータに対して、許可されたドメインのみをホワイトリスト化することで、内部ネットワークや不正な外部リソースへのアクセスを制限します。
    • httphttps以外のスキームを禁止し、file://gopher://のような不正なスキームを無効化します。
  2. ネットワークレベルの制御:
    • アプリケーションサーバーからの外部ネットワークアクセスを必要最小限に制限します。内部ネットワークやメタデータサービスへのアクセスをファイアウォールやセキュリティグループで制御します。
  3. プロキシの使用と制限:
    • 外部リクエストをプロキシサーバーを通じて行い、プロキシでアクセス可能なURLを制限することで、SSRF攻撃のリスクを低減します。
  4. タイムアウトとリダイレクト制御:
    • リクエストに対するタイムアウトを設定し、長時間のリクエスト実行や無限リダイレクトによる攻撃を防止します。リダイレクト先のURLも検証し、不正なリダイレクトを防ぎます。
  5. ロギングとモニタリング:
    • すべての外部リクエストをロギングし、不審なリクエストパターンを検出した場合にアラートを発生させるようにします。これにより、攻撃の兆候を早期に検出できます。

まとめ: SSRF攻撃は、サーバー側のリクエストを不正に操作して内部リソースや保護されたリソースにアクセスさせる攻撃です。ユーザー入力の厳格な検証、ネットワークレベルでのアクセス制限、プロキシの使用、リクエストのタイムアウト設定などの防止策を適用することで、この脆弱性を効果的に防ぐことができます。どの言語やプラットフォームでも、これらのベストプラクティスを実装することが推奨されます。