flawopen.com/ssrf/Java

● CWE-918 · Hoch
Sicherheitsforschung · FlawOpen

Server-Side Request Forgery in Java

How java.net.URL and HttpClient allow internal infrastructure scanning, and how to enforce IP address boundaries in Java.

💡 Einfache Erklärung (ELI5)

Stellen Sie sich vor, Sie schicken einen Boten, um ein Paket in einem öffentlichen Geschäft abzuholen, geben ihm aber die Adresse des Tresors im Büro des Geschäftsführers. Da der Bote einen internen Ausweis besitzt, öffnet er den Tresor und händigt Firmengeheimnisse aus.

Kernkonzepte & Begriffe

Web Application Security
Kernkomponente der Architektur, die von CWE-918 betroffen ist.
CWE-918
Standardmäßige Common Weakness Enumeration (CWE)-Klassifizierung für ssrf-java.
Defense-in-Depth
Mehrschichtige technische Verifikation und Laufzeit-Grenzenisolation.

Schritt-für-Schritt Angriffsablauf

Step 1

Eingabe Nicht Vertrauenswürdiger URLs

Die Anwendung akzeptiert externe URL-Parameter für Webhooks, Avatare oder PDF-Voransichten.

Step 2

Adressierung Interner Netzwerke

Der Angreifer übergibt eine Ziel-URL auf Cloud-Metadaten oder interne Loopback-Adressen (z. B. http://169.254.169.254/latest/meta-data/).

Step 3

Ungefilterter Socket-Ausgang

Der HTTP-Client des Servers sendet die Anfrage aus der geschützten VPC, ohne die Ziel-IP gegen private Subnetzbereiche abzugleichen.

Step 4

Exfiltration von Cloud-Zugangsdaten

Der interne Metadatendienst vertraut der Server-Anfrage und liefert temporäre IAM-Schlüssel und Tokens zurück.

Quellcode: Verwundbar vs. Sicher

✕ VERWUNDBARE IMPLEMENTIERUNG
// VULNERABLE: Naive java.net.URL openStream()
import java.net.URL;
import java.io.InputStream;
import javax.servlet.http.*;

public class ProxyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String targetUrl = req.getParameter("url");
        // Attacker input: http://169.254.169.254/latest/meta-data/
        try {
            URL url = new URL(targetUrl);
            InputStream in = url.openStream();
            in.transferTo(resp.getOutputStream());
        } catch (Exception e) {
            resp.setStatus(500);
        }
    }
}
✓ GEHÄRTETER SICHERHEITS-PATCH
// HARDENED: Resolve all IPs, assert non-private, and disable redirects
import java.net.*;
import java.net.http.*;
import java.time.Duration;
import javax.servlet.http.*;

public class ProxyServlet extends HttpServlet {
    private final HttpClient client = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(3))
        .followRedirects(HttpClient.Redirect.NEVER)
        .build();

    private boolean isSafeAddress(InetAddress addr) {
        return !addr.isLoopbackAddress() &&
               !addr.isSiteLocalAddress() &&
               !addr.isLinkLocalAddress() &&
               !addr.isAnyLocalAddress();
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String targetUrl = req.getParameter("url");
        try {
            URI uri = URI.create(targetUrl);
            if (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https")) {
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid scheme");
                return;
            }

            // 1. Resolve and validate all IP addresses
            InetAddress[] addresses = InetAddress.getAllByName(uri.getHost());
            for (InetAddress addr : addresses) {
                if (!isSafeAddress(addr)) {
                    resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access to internal IP prohibited");
                    return;
                }
            }

            // 2. Fetch using hardened client
            HttpRequest request = HttpRequest.newBuilder(uri)
                .timeout(Duration.ofSeconds(4))
                .GET()
                .build();

            HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
            resp.getOutputStream().write(response.body());

        } catch (Exception e) {
            resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
        }
    }
}

Checkliste für Engineering & Systemsicherheit

References