HIGH ssrfaxumjwt tokens

Ssrf in Axum with Jwt Tokens

Ssrf in Axum with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Server-Side Request Forgery (SSRF) in an Axum service that validates JWT tokens can occur when an endpoint accepts a user-supplied URL and performs an HTTP request on behalf of the caller, while also trusting the decoded claims of a JWT for authorization. Axum does not perform SSRF protection automatically; if a handler forwards requests to a host derived from user input (e.g., a webhook URL, a file location, or a metadata service endpoint), an attacker can supply a malicious URL that causes the server to reach internal services. The presence of JWT tokens can inadvertently make SSRR easier to exploit because developers may over-rely on the token for authorization and assume that internal destinations are safe once the token is verified.

Consider an Axum handler that accepts a JWT in the Authorization header and a target URL in the request body. The handler decodes the JWT to extract a user ID, then forwards the request to the provided URL, possibly using a server-side HTTP client. If the target URL is not strictly validated, an attacker can point it to http://169.254.169.254 (AWS instance metadata) or to internal Kubernetes services like http://kubernetes.default.svc. Because the handler trusts the JWT, it may skip additional authorization checks for the outbound request, effectively allowing the attacker to pivot from identity verification to internal network exploration or data exfiltration.

In practice, this maps to common OWASP API Top 10 API1:2023 — Broken Object Level Authorization when combined with API2:2023 — Broken Authentication (weak validation of the token scope or issuer) and API5:2023 — Injection (where the injected request is SSRF). Real-world examples include scanning internal metadata endpoints or abusing unauthenticated SSRF to reach Redis or Elasticsearch instances that are bound to localhost. middleBrick’s LLM/AI Security checks do not apply here, but its other checks such as Input Validation and Property Authorization help surface risky endpoint designs that could enable SSRF in JWT-protected routes.

Jwt Tokens-Specific Remediation in Axum — concrete code fixes

Remediation focuses on strict input validation, avoiding blind forwarding to user-supplied URLs, and ensuring JWT validation does not bypass network-level authorization. Below are concrete Axum examples that demonstrate a vulnerable pattern and a corrected implementation.

Vulnerable pattern

use axum::{routing::post, Json, Router};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
struct Claims {
    sub: String,
    scope: String,
}

#[derive(Deserialize)]
struct RequestBody {
    target_url: String,
}

async fn handler(
    Json(body): Json,
    auth: Option,
) -> String {
    let token = auth.and_then(|v| v.to_str().ok()).unwrap_or("");
    let decoded = decode::(
        token,
        &DecodingKey::from_secret("secret".as_ref()),
        &Validation::new(Algorithm::HS256),
    )
    .expect("invalid token")
    .claims;

    // Dangerous: forwards to any user-provided URL
    let client = reqwest::Client::new();
    let resp = client.get(&body.target_url)
        .header("Authorization", format!("Bearer {}", token))
        .send()
        .await
        .unwrap();
    format!("Status: {}", resp.status())
}

fn app() -> Router {
    Router::new().route("/forward", post(handler))
}

This pattern is risky because target_url is used without validation, and the handler forwards the original JWT, potentially over-privileged, to the destination.

Remediated pattern

use axum::{routing::post, Json, Router};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
use url::Url;

#[derive(Deserialize)]
struct Claims {
    sub: String,
    scope: String,
}

#[derive(Deserialize)]
struct RequestBody {
    target_path: String, // only a path, not a full URL
}

async fn handler(
    Json(body): Json,
    auth: Option,
) -> String {
    let token = auth.and_then(|v| v.to_str().ok()).unwrap_or("");
    let decoded = decode::(
        token,
        &DecodingKey::from_secret("secret".as_ref()),
        &Validation::new(Algorithm::HS256),
    )
    .expect("invalid token")
    .claims;

    // Validate path to prevent SSRF
    let parsed = Url::parse(&format!("https://api.example.com{}", body.target_path))
        .expect("invalid path");
    if parsed.host_str().map_or(true, |h| h != "api.example.com") {
        return "Forbidden".to_string();
    }

    // Use a server-side client with a fixed base URL
    let client = reqwest::Client::new();
    let resp = client.get(parsed.as_str())
        .bearer_auth(&token)
        .send()
        .await
        .unwrap();
    format!("Status: {}", resp.status())
}

fn app() -> Router {
    Router::new().route("/fetch", post(handler))
}

Key mitigations include:

  • Accept only a path (target_path) instead of a full URL, and resolve it against a fixed base domain.
  • Validate the resolved host against an allowlist to prevent redirection to internal or external malicious endpoints.
  • Do not blindly forward the incoming JWT to the destination; instead, use a scoped token or server-side credentials appropriate for the backend call.
  • Apply stricter validation on JWT claims (e.g., scope and iss) to ensure the request is authorized for the intended action.

Related CWEs: ssrf

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

Frequently Asked Questions

Does middleBrick detect SSRF in JWT-protected Axum endpoints?
middleBrick scans unauthenticated attack surfaces and can identify SSRF-prone endpoints and weak JWT validation patterns, but it does not fix or block findings; it provides prioritized findings with remediation guidance.
How can I prevent SSRF when forwarding requests in Axum?
Validate and restrict target URLs to a fixed host, avoid forwarding user-supplied URLs directly, use server-side HTTP clients with limited scopes, and ensure JWT validation is coupled with network-level authorization checks.