HIGH actixrustdns rebinding

Dns Rebinding in Actix (Rust)

Dns Rebinding in Actix with Rust — how this specific combination creates or exposes the vulnerability

DNS Rebinding is a client-side attack where a malicious webpage changes the DNS resolution of a hostname to point to an internal IP address after initial page load. When an Actix web application is hosted on a public domain but internally trusts same-origin requests, an attacker can bypass IP-based or network-based trust by first resolving a benign hostname to the public address, then rebinding it to an internal service such as 127.0.0.1 or a corporate RFC1918 address. Because Actix services often expose admin or diagnostic endpoints on localhost and rely on origin checks rather than strict network boundary enforcement, this rebinding can trick the server into processing requests as if they originated from a trusted network.

In Rust, Actix does not inherently validate that a request’s target origin matches the network zone of the connecting peer. If the application uses hostname-based access control or trusts the Host header without additional verification, an attacker-controlled page can make cross-origin requests that appear legitimate. For example, a JavaScript fetch initiated from https://example.com can rebind to http://internal-service.local and reach an Actix endpoint listening on 127.0.0.1:8080/health. Because Actix routes are matched to paths rather than network zones by default, the server may process the request and return internal information or trigger internal logic, leading to unauthorized access or data exposure.

middleBrick scans such misconfigurations by testing unauthenticated endpoints and cross-referencing OpenAPI specs with runtime behavior. In environments using Actix with Rust, it is particularly important to validate that endpoints do not rely on implicit trust of internal network assumptions. Without explicit network zone validation, even stateless APIs can become pivot points for internal reconnaissance. The scanner checks for missing origin validation, overly permissive CORS, and endpoints that do not enforce strict source verification, flagging findings related to BOLA/IDOR and Property Authorization where applicable.

Rust-Specific Remediation in Actix — concrete code fixes

To mitigate DNS Rebinding in Actix services written in Rust, enforce strict origin and network validation at the handler or middleware level. Do not rely on the Host header alone. Instead, validate the socket address of the connection and compare it against an allowlist of permitted internal interfaces. For applications that must expose services locally, bind to 127.0.0.1 and avoid binding to 0.0.0.0 unless a firewall or reverse proxy restricts external access.

Below are concrete Rust code examples for Actix that demonstrate how to implement these controls.

1. Restricting Binding Address

Ensure the Actix server only listens on loopback when no public exposure is required:

use actix_web::{web, App, HttpServer, Responder};

async fn health() -> impl Responder {
    "OK"
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // Only accept connections from localhost
    HttpServer::new(|| {
        App::new()
            .route("/health", web::get().to(health))
    })
    .bind("127.0.0.1:8080")?  // Explicit loopback binding
    .run()
    .await
}

2. Validating Remote Address in Middleware

Create a middleware that checks the peer’s IP against permitted ranges and rejects requests from unexpected network zones:

use actix_web::{dev::ServiceRequest, Error, middleware::Next};
use actix_web::body::BoxBody;
use std::net::IpAddr;

async fn validate_remote_addr(req: ServiceRequest, next: Next<BoxBody>) -> Result<actix_web::dev::ServiceResponse<BoxBody>, Error> {
    let peer_addr = req.connection_info().realip_remote_addr()
        .map(|s| s.parse().unwrap_or_else(|_| "0.0.0.0".parse().unwrap()))
        .unwrap_or("0.0.0.0".parse().unwrap());

    // Allow only internal RFC1918 or loopback ranges as appropriate
    if is_allowed_ip(peer_addr) {
        next.call(req).await
    } else {
        Err(actix_web::error::ErrorForbidden("Network access denied"))
    }
}

fn is_allowed_ip(ip: IpAddr) -> bool {
    match ip {
        IpAddr::V4(a) => a.is_loopback() || a.octets() == [10, 0, 0, 1], // example allowlist
        IpAddr::V6(a) => a.is_loopback() || a.segments() == [0, 0, 0, 0, 0, 0, 0, 1],
    }
}

// Integration in App configuration
// App::new()
//     .wrap_fn(|req, srv| validate_remote_addr(req, srv))

3. Enforcing Strict CORS Policies

Limit CORS to known origins and avoid wildcard usage:

use actix_cors::Cors;

let cors = Cors::default()
    .allowed_origin("https://trusted.example.com")
    .allowed_methods(vec!["GET"])
    .max_age(3600);

HttpServer::new(move || {
    App::new()
        .wrap(cors.clone())
        .route("/api/data", web::get().to(|| async { "data" }))
})
.bind("0.0.0.0:8080")?
.run()
.await

By combining restricted binding, peer validation, and strict CORS, Rust Actix services can effectively neutralize DNS Rebinding risks. middleBrick can verify these controls by scanning endpoints and confirming that responses do not vary based on rebinding attempts, ensuring that internal logic remains protected.

Frequently Asked Questions

Can DNS Rebinding affect APIs that require authentication?
Yes. Even authenticated APIs can be targeted if the attacker can obtain or guess valid credentials. Defense-in-depth with IP validation and origin checks is essential regardless of authentication.
Does middleBrick actively exploit DNS Rebinding during scans?
middleBrick detects conditions that enable DNS Rebinding by testing unauthenticated attack surfaces and comparing spec definitions with runtime behavior. It does not perform active exploitation but reports findings and provides remediation guidance.