HIGH ssrf server sideactixbasic auth

Ssrf Server Side in Actix with Basic Auth

Ssrf Server Side in Actix with Basic Auth — how this specific combination creates or exposes the vulnerability

Server-side request forgery (SSRF) in Actix applications that also use HTTP Basic Authentication can occur when user-controlled input is used to form outbound HTTP requests without adequate validation. Even when endpoints are protected behind Basic Auth, SSRF risks remain because the server, not the client, holds credentials and decides where to connect. An attacker can supply a URL that causes the server to reach internal endpoints, cloud metadata services, or restricted administrative interfaces, bypassing what appears to be perimeter authentication.

In Actix, handlers that accept a URL parameter or header and forward it with a client-supplied credential or a hardcoded credential can be abused if the destination is not strictly constrained. For example, an endpoint that accepts a target URL and uses Basic Auth to authenticate to that target may be tricked into requesting http://169.169.254.169/latest/meta-data/ (AWS instance metadata) or internal Kubernetes services like http://kubernetes.default.svc. MiddleBrick’s unauthenticated scan would flag this as SSRF by submitting payloads that attempt internal resolution and observing responses that should not be reachable from the public surface.

OpenAPI/Swagger analysis helps surface these risks when path and parameter definitions allow dynamic URLs without strict schema enforcement. If your Actix API exposes an endpoint such as /fetch?url= and uses middleware to add Basic Auth headers before proxying, scanning can detect whether responses include sensitive internal data or metadata. Findings will map to the OWASP API Top 10 A05:2023 Security Misconfiguration and A01:2023 Broken Access Control, providing remediation guidance such as strict allowlists for hostnames and blocking private IP ranges.

Basic Auth-Specific Remediation in Actix — concrete code fixes

To reduce SSRF risk in Actix when using Basic Authentication, validate and constrain all user-supplied URLs and prefer static, allowlisted destinations. Avoid dynamically constructing target URLs from unchecked inputs. When proxying or making outbound calls, enforce strict hostname allowlists that exclude private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and reserved IPs such as 127.0.0.1 and 169.254.169.254.

Below are concrete Actix examples that combine Basic Auth with safer request handling. The unsafe example illustrates a vulnerable pattern; the safe example demonstrates hardened handling.

Unsafe pattern (illustrative)

use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};

async fn unsafe_fetch(query: web::Query>) -> impl Responder {
    let target = query.get("url").unwrap_or(&"http://example.com".to_string());
    let username = "admin";
    let password = "secret";
    let auth = format!("{}:{}", username, password);
    let auth_header_value = HeaderValue::from_str(&format!("Basic {}", base64::encode(auth.as_bytes()))).unwrap();
    let mut headers = HeaderMap::new();
    headers.insert(AUTHORIZATION, auth_header_value);
    let client = reqwest::Client::new();
    match client.get(target.as_str())
        .headers(headers)
        .send()
        .await {
        Ok(resp) => HttpResponse::Ok().body(resp.text().await.unwrap_or_default()),
        Err(e) => HttpResponse::BadRequest().body(e.to_string()),
    }
}

This pattern takes the url query parameter directly and uses hardcoded Basic Auth credentials to reach it. An attacker can supply url=http://169.169.254.169/latest/meta-data/ or other internal targets, leading to SSRF.

Safe pattern with strict validation

use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use std::net::{IpAddr, Ipv4Addr};

fn is_private_ip(ip: IpAddr) -> bool {
    match ip {
        IpAddr::V4(v4) => {
            v4.is_private() || v4.is_loopback() || v4.is_link_local() || v4.octets()[0] == 169 && v4.octets()[1] == 254
        }
        IpAddr::V6(v6) => v6.is_loopback() || v6.is_link_local() || v6.is_unique_local(),
    }
}

async fn safe_fetch(query: web::Query>) -> impl Responder {
    let target = query.get("url").unwrap_or(&"https://api.example.com/data".to_string());
    // Strict allowlist: only permit specific hostnames
    let allowed_hosts = ["api.example.com", "data.partner.com"];
    let parsed = match url::Url::parse(target) {
        Ok(u) => u,
        Err(_) => return HttpResponse::BadRequest().body("Invalid URL"),
    };
    if !allowed_hosts.contains(&parsed.host_str().unwrap_or("")) {
        return HttpResponse::BadRequest().body("Host not allowed");
    }
    let ip = match parsed.host_ip() {
        Some(ip) => ip,
        None => return HttpResponse::BadRequest().body("Cannot resolve host"),
    };
    if is_private_ip(ip) {
        return HttpResponse::BadRequest().body("Private IP not allowed");
    }
    let username = "admin";
    let password = "secret";
    let auth = format!("{}:{}", username, password);
    let auth_header_value = match HeaderValue::from_str(&format!("Basic {}", base64::encode(auth.as_bytes()))) {
        Ok(v) => v,
        Err(_) => return HttpResponse::InternalServerError().body("Encoding error"),
    };
    let mut headers = HeaderMap::new();
    headers.insert(AUTHORIZATION, auth_header_value);
    let client = reqwest::Client::new();
    match client.get(parsed.as_str())
        .headers(headers)
        .send()
        .await {
        Ok(resp) => HttpResponse::Ok().body(resp.text().await.unwrap_or_default()),
        Err(e) => HttpResponse::BadRequest().body(e.to_string()),
    }
}

Key mitigations in the safe pattern:

  • Host allowlist limits outbound calls to known partners.
  • URL parsing and IP validation block private and reserved addresses, including 169.254.x.x (link-local) which is commonly used for cloud metadata endpoints.
  • Basic Auth credentials remain on the server side for outbound calls, avoiding exposure to clients.

These changes align with remediation guidance returned by middleBrick scans, which may reference compliance frameworks such as OWASP API Top 10 and provide prioritized findings with severity levels and specific fixes.

Frequently Asked Questions

Can middleBrick detect SSRF in Actix APIs that use Basic Auth?
Yes. middleBrick scans unauthenticated attack surfaces and can detect SSRF by attempting internal and cloud metadata endpoints. Findings include severity, remediation guidance, and mapping to frameworks like OWASP API Top 10.
Does middleBrick fix the vulnerabilities it finds in Actix APIs?
No. middleBrick detects and reports findings with remediation guidance but does not fix, patch, block, or remediate. Developers should apply the provided guidance, such as input validation and hostname allowlists, to address SSRF and related issues.