HIGH ssrf server sideactix

Ssrf Server Side in Actix

How SSRF Manifests in Actix Applications

Server-Side Request Forgery (SSRF) in Actix applications occurs when user-controlled input is used to construct URLs for outbound HTTP requests without proper validation. In Actix, this typically happens in handler functions where parameters from HTTP requests are directly passed to HTTP clients or URL parsing functions.

A common pattern in Actix applications involves using the http crate or reqwest to make outbound requests. When user input like user_id or redirect_url is incorporated into these requests without validation, attackers can manipulate the input to target internal services. For example:

async fn proxy_handler(&self, req: HttpRequest) -> impl Responder {
    let target_url = req.query("url").unwrap_or("http://default").to_string();
    let client = reqwest::Client::new();
    let res = client.get(&target_url).send().await.unwrap();
    HttpResponse::build(res.status()).body(res.text().await.unwrap())
}

This Actix handler directly uses the url query parameter to make an outbound request. An attacker could supply http://localhost:8080/internal or http://169.254.169.254/latest/meta-data/ to access internal metadata services or internal APIs.

Actix applications often integrate with cloud services, databases, or internal microservices. SSRF vulnerabilities become particularly dangerous when Actix handlers proxy requests to these services. The framework's async nature means these requests execute immediately, potentially exposing internal network services that aren't meant to be publicly accessible.

Another Actix-specific manifestation involves using the actix-web-httpclient or similar crates for outbound requests. When user input flows through Actix's request extraction and validation pipeline without proper sanitization, SSRF vulnerabilities emerge. The framework's strong typing can actually make these vulnerabilities more subtle, as developers might assume type safety provides security guarantees.

Actix-Specific Detection Methods

Detecting SSRF in Actix applications requires both static analysis and runtime scanning. Static analysis should focus on identifying patterns where user input flows to URL construction or HTTP client calls. Look for:

  • Query parameters, path parameters, or JSON body fields used in URL construction
  • Direct use of reqwest::get(), http::Request::get(), or similar outbound request functions
  • URL parsing without validation (Url::parse() with user input)
  • Configuration files with templated URLs containing user data

Runtime scanning with middleBrick provides comprehensive SSRF detection for Actix applications. The scanner tests unauthenticated endpoints by sending payloads designed to trigger SSRF behavior. middleBrick's black-box scanning approach is particularly effective because it doesn't require access to source code or internal APIs.

middleBrick's SSRF detection includes testing for:

  • Localhost and loopback address access attempts
  • Private IP range requests (10.x, 172.16-31.x, 192.168.x)
  • Link-local and multicast address access
  • Cloud provider metadata service endpoints (169.254.169.254, 169.254.170.2)
  • Internal domain names and DNS rebinding attempts

The scanner provides a security score (0-100) with specific findings for each vulnerability category. For SSRF, middleBrick reports the exact payloads that triggered internal service access, making remediation straightforward. The tool also checks for missing rate limiting and input validation, which often accompany SSRF vulnerabilities.

middleBrick's continuous monitoring capability is valuable for Actix applications in production. APIs can be scanned on a configurable schedule, with alerts sent when SSRF vulnerabilities are detected or when security scores drop below thresholds. This proactive approach helps catch SSRF issues before attackers exploit them.

Actix-Specific Remediation Techniques

Remediating SSRF in Actix applications requires a defense-in-depth approach. The most effective strategy combines input validation, allowlisting, and architectural controls. Here's how to implement these in Actix:

Input validation should occur at the handler level before any URL construction. Use Actix's strong typing to extract and validate parameters:

use actix_web::{get, HttpResponse, Responder};
use url::Url;
use std::net::IpAddr;

#[get("/proxy")]
async fn proxy_handler(
    query: actix_web::web::Query<QueryParams>,
) -> impl Responder {
    // Validate URL format
    let target_url = match Url::parse(&query.url) {
        Ok(url) if is_allowed_url(&url) => url,
        _ => return HttpResponse::BadRequest().body("Invalid URL"),
    };

    // Check for private IP addresses
    if is_private_ip(&target_url.host_str().unwrap_or("")) {
        return HttpResponse::BadRequest().body("Private addresses not allowed");
    }

    // Proceed with request
    let client = reqwest::Client::new();
    let res = client.get(target_url).send().await.unwrap();
    HttpResponse::build(res.status()).body(res.text().await.unwrap())
}

fn is_allowed_url(url: &Url) -> bool {
    // Allowlist specific domains
    matches!(url.host_str(), Some("api.example.com") | Some("cdn.example.net"))
}

fn is_private_ip(host: &str) -> bool {
    if let Ok(ip) = host.parse::() {
        ip.is_private() || ip.is_loopback()
    } else {
        false
    }
}

This Actix handler validates URLs against an allowlist and checks for private IP addresses before making outbound requests. The is_allowed_url function restricts requests to specific trusted domains, while is_private_ip blocks internal network access.

For more complex scenarios, implement a dedicated URL validation service:

use actix_web::middleware::Next;
use url::Url;
use std::collections::HashSet;

pub struct UrlValidationMiddleware {
    allowed_hosts: HashSet<String>,
}

impl actix_web::middleware::Transform for UrlValidationMiddleware
where
    S: actix_web::dev::Service<Request = actix_web::dev::ServiceRequest, Response = actix_web::dev::ServiceResponse>,
{
    type Request = actix_web::dev::ServiceRequest;
    type Response = actix_web::dev::ServiceResponse;
    type Error = actix_web::Error;
    type Transform = UrlValidationMiddlewareService;

    fn new_transform(&self, service: S) -> Self::Transform {
        UrlValidationMiddlewareService {
            service,
            allowed_hosts: self.allowed_hosts.clone(),
        }
    }
}

pub struct UrlValidationMiddlewareService<S> {
    service: S,
    allowed_hosts: HashSet<String>,
}

impl<S> actix_web::dev::Service for UrlValidationMiddlewareService<S>
where
    S: actix_web::dev::Service<Request = actix_web::dev::ServiceRequest, Response = actix_web::dev::ServiceResponse>,
{
    type Request = actix_web::dev::ServiceRequest;
    type Response = actix_web::dev::ServiceResponse;
    type Error = actix_web::Error;
    type Future = actix_web::dev::ServiceResponseFuture;

    actix_web::dev::forward_ready!(service);

    fn call(&mut self, req: Self::Request) -> Self::Future {
        // Check if this request needs URL validation
        if let Some(url) = extract_target_url(&req) {
            if !self.is_url_allowed(&url) {
                return Box::pin(async move {
                    Ok(req.error_response(
                        actix_web::error::InternalError::new(
                            "URL not allowed",
                            actix_web::http::StatusCode::BAD_REQUEST,
                        ),
                    ))
                });
            }
        }
        self.service.call(req)
    }
}

fn extract_target_url(req: &actix_web::dev::ServiceRequest) -> Option<Url> {
    // Extract URL from query parameters or body
    None
}

fn is_url_allowed(url: &Url) -> bool {
    // Implement allowlist logic
    true
}

This middleware approach centralizes URL validation across all Actix handlers, ensuring consistent SSRF protection throughout the application.

Additional architectural controls include:

  • Network segmentation to isolate internal services
  • DNS filtering to block resolution of internal domains
  • Outbound proxy configuration with strict allowlisting
  • Rate limiting on outbound requests to prevent abuse
  • Monitoring and alerting for unusual outbound request patterns

middleBrick's remediation guidance specifically addresses Actix patterns, providing code examples and configuration recommendations tailored to Rust and Actix's async architecture. The tool's findings include severity levels and step-by-step remediation instructions that integrate seamlessly with Actix's error handling and middleware patterns.

Frequently Asked Questions

How does SSRF differ in Actix applications compared to other frameworks?
SSRF in Actix applications often involves Rust-specific patterns like using the reqwest crate for outbound requests and Actix's async handler functions. The framework's strong typing can make SSRF vulnerabilities more subtle, as developers might assume type safety provides security guarantees. Actix's middleware system also allows for centralized SSRF protection through request validation layers.
Can middleBrick detect SSRF in Actix applications without access to source code?
Yes, middleBrick uses black-box scanning to detect SSRF in Actix applications. The scanner sends payloads designed to trigger SSRF behavior and analyzes responses for signs of internal service access. This approach works regardless of the underlying framework or programming language, making it effective for Actix applications without requiring source code access.