SSRF via HTTP redirect following — scanner reaches cloud metadata endpoints

Author: RyujiyasuCreated Mar 9, 2026Updated Mar 9, 2026

Summary

Tsunami's HTTP client follows redirects by default (DEFAULT_FOLLOW_REDIRECTS = true), and the OkHttp-level redirect is resolved transparently before Tsunami's in-scope URL filter is applied. An attacker-controlled scan target can redirect the scanner to cloud instance metadata endpoints, exfiltrating GCP/AWS/Azure credentials.

Vulnerable Code

Root cause 1: HttpClientModule.java:335 — redirects enabled by default

java
private static final boolean DEFAULT_FOLLOW_REDIRECTS = true;

Root cause 2: OkHttp resolves redirects before SimpleCrawlAction.java's scope check

java
// SimpleCrawlAction.java:96-101, 139-166
// The scope filter is applied AFTER OkHttp has already followed HTTP 302/301 redirects
.filter(crawlTarget -> CrawlConfigUtils.isCrawlTargetInScope(crawlConfig, crawlTarget))
// OkHttp's redirect following happens at the HTTP layer, returning the final response
// directly — isCrawlTargetInScope() never sees the redirect destination URL

Root cause 3: tsunami.yaml ships with trust_all_certificates: true

And HttpClientModule.java:163-175 disables hostname verification:

java
.hostnameVerifier((hostname, session) -> true)

Attack Scenario

  1. Attacker controls evil.example.com
  2. Tsunami operator scans evil.example.com (normal usage)
  3. Server returns HTTP 302 Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/
  4. OkHttp silently follows redirect to cloud metadata endpoint (from the scanner's cloud VM)
  5. Response (IAM credentials JSON) is stored as a CrawlResult in Tsunami's scan output

Suggested Fix

Validate redirect destination URLs before following them: reject private IP ranges, cloud metadata endpoints, and loopback addresses. Consider adding a CheckRedirect policy to the OkHttp client.

Source: google/tsunami-security-scanner