HIGH ssrfginbearer tokens

Ssrf in Gin with Bearer Tokens

Ssrf in Gin with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Server-Side Request Forgery (SSRF) in Gin when Bearer Tokens are involved occurs when an attacker can coerce the server into making authenticated outbound HTTP requests to internal or restricted endpoints. In many APIs built with Gin, developers implement proxy-like routes that forward requests to downstream services and attach Authorization headers based on incoming request headers. If the upstream URL is derived from user input and the Authorization header is sourced from the request (e.g., via a forwarded Bearer token or a header copied from the client), the server can be made to perform authenticated requests to internal metadata services, cloud instance metadata APIs, or administrative interfaces.

For example, consider a Gin route that accepts a target URL and forwards a request while propagating a Bearer token extracted from the client’s Authorization header:

func ProxyHandler(c *gin.Context) {
    target := c.Query("url")
    token := c.GetHeader("Authorization")
    if token == "" {
        c.JSON(401, gin.H{"error": "missing authorization"})
        return
    }
    req, _ := http.NewRequest("GET", target, nil)
    req.Header.Set("Authorization", token)
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    c.Data(resp.StatusCode, "application/octet-stream", body)
}

If an attacker can control the target parameter, they can set it to http://169.254.169.254/latest/meta-data/iam/security-credentials/ on an EC2 instance and use the forwarded Bearer token (which may be trusted internally) to access credentials. Even without cloud metadata, SSRF can bypass network ACLs because the server-side request originates from a trusted zone and carries a valid Bearer token. The presence of Bearer tokens does not cause SSRF by itself, but it amplifies impact: an SSRF that authenticates as a service account can read sensitive internal resources, call internal admin endpoints, or chain into other services that trust intra-service tokens.

In the context of middleBrick’s checks, this pattern would be flagged under SSRF and BFLA/Privilege Escalation: the scanner tests whether user-supplied URLs can trigger authenticated outbound requests and whether authorization headers derived from the request can be leveraged to escalate access. The scan also aligns with OWASP API Top 10 A05:2023 (Broken Function Level Authorization) when token propagation logic is coupled with insecure routing logic.

Bearer Tokens-Specific Remediation in Gin — concrete code fixes

Remediation focuses on removing uncontrolled Bearer token propagation and validating or rejecting user-supplied URLs that can lead to internal endpoints. Below are concrete, safe patterns for Gin handlers.

1. Do not forward caller-supplied Authorization headers

Strip or ignore incoming Authorization headers when constructing outbound requests. Use a fixed token stored securely (e.g., from environment variables) or use mutual TLS / service identity instead of forwarding client tokens.

func SafeProxyHandler(c *gin.Context) {
    target := c.Query("url")
    // Validate target against an allowlist or strict prefix
    if !strings.HasPrefix(target, "https://api.example.com/") {
        c.JSON(400, gin.H{"error": "invalid target"})
        return
    }
    // Use a service-bound token, not the caller’s header
    token := os.Getenv("SERVICE_TOKEN")
    if token == "" {
        c.JSON(500, gin.H{"error": "service token not configured"})
        return
    }
    req, err := http.NewRequest("GET", target, nil)
    if err != nil {
        c.JSON(500, gin.H{"error": "invalid request"})
        return
    }
    req.Header.Set("Authorization", "Bearer "+token)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        c.JSON(502, gin.H{"error": "upstream error"})
        return
    }
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    c.Data(resp.StatusCode, "application/json", body)
}

2. Strict URL allowlisting and no user-controlled redirects

Do not accept free-form URLs. Either hardcode endpoints or validate against a strict prefix and path pattern. Reject parameters that could resolve to internal IPs or cloud metadata addresses.

var allowedPrefix = "https://api.example.com/v1/"
func ValidateTarget(target string) bool {
    u, err := url.Parse(target)
    if err != nil {
        return false
    }
    if u.Scheme != "https" {
        return false
    }
    if !strings.HasPrefix(u.Host, "api.example.com") {
        return false
    }
    if !strings.HasPrefix(u.Path, "/v1/") {
        return false
    }
    return true
}

3. Use outbound network policies and service identity

While not code, ensure the Gin service runs with network policies that restrict egress to known endpoints and avoid binding service tokens to inbound request contexts. Prefer workload identity (e.g., Kubernetes service accounts) over static bearer tokens when possible.

These changes ensure that Bearer tokens are not reflected or proxied from client input, mitigating SSRR risks and reducing the blast radius of any remaining SSRF vectors.

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

Can middleBrick detect SSRF in Gin APIs that forward requests with Bearer tokens?
Yes. middleBrick runs SSRF and BFLA/Privilege Escalation checks that identify whether user-controlled URLs can trigger authenticated outbound requests, including patterns where Bearer tokens from headers are propagated.
Does the middleBrick CLI produce remediation guidance for SSRF in Gin?
Yes. The middlebrick scan command outputs prioritized findings with severity and remediation guidance, including specific code patterns to avoid or adopt for safer token handling in Gin.