HIGH ssrfaxumbasic auth

Ssrf in Axum with Basic Auth

Ssrf in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability

Server-Side Request Forgery (SSRF) in an Axum service that uses HTTP Basic Authentication can occur when user-controlled input is used to form outbound HTTP requests and the service is configured to forward credentials through the same client. In Axum, a handler that receives a URL from an API client and then uses a shared HTTP client to fetch that URL may inadvertently allow an attacker to direct internal requests or reach restricted resources. Because Basic Auth credentials are often attached to a client builder (e.g., via headers or a credentialed connector), a maliciously supplied host in the user input can cause the server to authenticate to internal services or metadata endpoints with the same privileges as the service account.

Consider an Axum handler that accepts a URL parameter and uses reqwest to fetch it. If the client is built with default behavior that attaches Basic Auth headers based on environment variables or runtime configuration, an attacker can supply an internal address (such as http://169.254.169.254/latest/meta-data/iam/security-credentials/) and the request will be executed with the service’s credentials. This exposes cloud instance metadata, internal admin panels, or misconfigured services that expect requests only from trusted internal networks. The risk is amplified when the Axum runtime is deployed inside a cloud environment where metadata services are reachable from within the instance.

An example of a vulnerable Axum handler:

use axum::{routing::get, Router};
use reqwest::Client;
use std::net::SocketAddr;

async fn handler(url: String) -> String {
    let client = Client::new();
    let response = client.get(&url).send().await.unwrap().text().await.unwrap();
    response
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/fetch", get(handler));
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}

In this example, if the service account running Axum has Basic Auth credentials configured at the HTTP client level (for example via a system-wide proxy or default headers), and the handler does not validate or sanitize the incoming URL, an SSRF vector exists. An attacker could supply a URL that targets internal services or cloud metadata, and the outbound request may succeed because the client includes the inherited authentication context.

The interaction with Basic Auth in this scenario does not introduce SSRF by itself, but it can turn a simple SSRF into a high-severity finding by enabling authenticated internal requests. middleBrick detects SSRF findings and maps them to the OWASP API Top 10 and other compliance frameworks, providing remediation guidance rather than attempting to block or fix the service.

Basic Auth-Specific Remediation in Axum — concrete code fixes

To mitigate SSRF when using Basic Auth in Axum, ensure that outbound requests are constructed from strictly controlled endpoints and that credentials are not automatically forwarded to user-supplied targets. Prefer explicit configuration for each request, avoid sharing a single client with global authentication when handling arbitrary URLs, and validate hostnames and paths before issuing requests.

One approach is to create a dedicated client without default authentication and to manually add Basic Auth headers only for known, safe destinations. This prevents credentials from being sent to arbitrary user-provided hosts. Below is a secure Axum handler example that decodes Basic Auth credentials only for specific internal services and validates the target host before proceeding.

use axum::{routing::get, Router, extract::Query};
use reqwest::{Client, header::{AUTHORIZATION, HeaderValue}};
use std::net::SocketAddr;
use base64::encode;

async fn safe_handler(Query(params): Query<Params>) -> String {
    // Allowlist of permitted hosts
    let allowed_hosts = ["internal.service.local", "api.partner.example.com"];
    if !allowed_hosts.contains(&params.host.as_str()) {
        return String::from("Host not allowed");
    }

    // Build client without default auth
    let client = Client::new();

    // Construct Basic Auth header only for allowed hosts
    let credentials = format!("{}:{}", params.username, params.password);
    let encoded = encode(credentials.as_bytes());
    let auth_value = HeaderValue::from_str(&format!("Basic {}", encoded)).unwrap();

    let url = format!("https://{}/v1/resource", params.host);
    let response = client.get(&url)
        .header(AUTHORIZATION, auth_value)
        .send()
        .await
        .unwrap()
        .text()
        .await
        .unwrap();
    response
}

#[derive(serde::Deserialize)]
struct Params {
    host: String,
    username: String,
    password: String,
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/fetch-safe", get(safe_handler));
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}

This pattern ensures that the service does not automatically propagate credentials to any endpoint. By validating the host against an allowlist and explicitly constructing the Authorization header only when necessary, you reduce the attack surface for SSRF. middleBrick can identify remaining misconfigurations through its unauthenticated scan, and the Pro plan supports continuous monitoring to catch regressions in API behavior.

Additionally, avoid storing Basic Auth credentials in environment variables that are globally accessible to the runtime unless they are strictly required. Instead, use scoped configuration and runtime checks. The CLI tool (middlebrick scan <url>) and the GitHub Action can be integrated into CI/CD to enforce that only vetted endpoints are allowed in your API definitions.

Related CWEs: ssrf

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

Frequently Asked Questions

Can SSRF be detected by scanning an OpenAPI specification without authentication?
Yes. middleBrick scans the unauthenticated attack surface and cross-references the OpenAPI/Swagger spec (including $ref resolution) with runtime findings. Even without Basic Auth or other credentials, the scanner can identify endpoints that accept arbitrary URLs and highlight SSRF risks, complemented by its LLM/AI Security checks when relevant.
Does middleBrick automatically fix Basic Auth and SSRF issues in Axum services?
No. middleBrick detects and reports findings with severity, prioritization, and remediation guidance. It does not patch, block, or modify your code. You should apply concrete fixes such as host allowlists, explicit credential handling, and input validation in your Axum handlers.