HIGH dns rebindingactixdynamodb

Dns Rebinding in Actix with Dynamodb

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

DNS rebinding is a client-side attack where a malicious webpage resolves a domain name to an attacker-controlled IP address after the initial page load, often bypassing same-origin policies. When this technique is combined with an Actix web server that exposes an internal DynamoDB endpoint, the risk is an unauthorized data access path that appears to originate from a trusted source.

In this scenario, an attacker might host a page that causes the browser to send requests to an internal Actix service. If that Actix service proxies or directly forwards requests to a DynamoDB endpoint using IAM credentials or a locally reachable instance, the rebinding can trick the service into making privileged calls. For example, a compromised browser context may resolve internal-dynamodb.local to the attacker’s server after initial resolution to a corporate network IP, and the Actix backend may still forward queries because it trusts internal headers or IPs.

An illustrative request chain includes:

  • The victim loads a malicious site that uses JavaScript to flip DNS records for dynamodb-proxy.actix.internal.
  • The Actix application, expecting internal traffic, forwards the request to DynamoDB using a hardcoded table name and IAM role.
  • Because the rebinding bypasses network-based trust assumptions, the Actix service may inadvertently expose scan or query patterns that reveal data structure or sensitive records.

middleBrick detects this class of issue by checking whether an API surface accepts requests that do not enforce strict source validation and whether responses include indicators of internal service references. The scan flags the exposed DynamoDB surface in Actix when endpoints do not validate origin headers or enforce strict CORS and network isolation, aligning with the SSRF and BOLA/IDOR checks in the 12 security checks.

To illustrate a vulnerable Actix route that directly forwards to DynamoDB without origin checks, consider the following code pattern (shown for context, not as a recommendation):

async fn forward_to_dynamodb(req: HttpRequest, body: String) -> Result<HttpResponse> {
    let client = DynamoDbClient::new(&aws_config::load_from_env().await);
    let input = serde_json::from_str::<HashMap<String, String>>(&body)?;
    let table_name = input.get("table").unwrap_or(&"default".to_string());
    // Vulnerable: no origin validation, exposed internal endpoint
    let resp = client.scan().table_name(table_name).send().await?;
    Ok(HttpResponse::Ok().json(resp))
}

This pattern highlights how an Actix endpoint that accepts a table name from the caller and forwards to DynamoDB without validating the caller’s network origin can be abused via DNS rebinding if the service is reachable from a browser context.

Dynamodb-Specific Remediation in Actix — concrete code fixes

Remediation centers on ensuring that any interaction between Actix and DynamoDB explicitly validates the request origin, enforces least privilege IAM, and avoids exposing internal table names or endpoints to the client. Below are concrete, safe patterns for Actix services that must interact with DynamoDB.

1. Validate Origin and Enforce CORS

Use Actix’s CORS middleware to restrict origins and avoid forwarding requests from untrusted sources. Combine this with explicit header checks for sensitive routes.

use actix_cors::Cors;
use actix_web::{web, App, HttpServer, HttpResponse};

async fn safe_handler() -> HttpResponse {
    HttpResponse::Ok().body("Access granted")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let cors = Cors::default()
        .allowed_origin("https://trusted.example.com")
        .allowed_methods(vec!["GET", "POST"])
        .allowed_headers(vec![actix_web::http::header::AUTHORIZATION, actix_web::http::header::ACCEPT])
        .max_age(3600);

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

2. Use Parameterized Queries and Avoid Dynamic Table Names

Instead of forwarding a caller-supplied table name, use a predefined table and parameterized queries. This prevents table enumeration and injection via rebinding or other means.

use aws_sdk_dynamodb::Client;
use std::collections::HashMap;

async fn query_fixed_table(client: &Client) -> Result<(), aws_sdk_dynamodb::error::SdkError<aws_sdk_dynamodb::operation::scan::ScanError>> {
    let resp = client.scan()
        .table_name("fixed-audit-log")
        .send()
        .await?;
    // Process items safely
    for item in resp.items().unwrap_or_default() {
        if let Some(id) = item.get("id") {
            println!("Item ID: {:?}", id);
        }
    }
    Ok(())
}

3. Enforce IAM Policies with Least Privilege

Ensure the Actix service’s IAM role only permits the specific DynamoDB actions needed (e.g., dynamodb:Scan on a single table) and does not allow wildcard resource access. This reduces the impact of a compromised route.

{ 
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:Scan"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/fixed-audit-log"
    }
  ]
}

4. Add Request Validation and Input Sanitization

Even when using a fixed table, validate and sanitize any input fields used in expressions or filters to avoid injection-style issues via crafted payloads delivered through rebinding.

fn validate_filter(value: &str) -> bool {
    // Allow only alphanumeric and limited punctuation
    value.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_')
}

async fn filtered_query(client: &Client, filter_val: &str) -> Result<(), String> {
    if !validate_filter(filter_val) {
        return Err("Invalid filter".into());
    }
    client.scan()
        .table_name("fixed-audit-log")
        .set_filter_expression(Some("#status = :val".into()))
        .set_expression_attribute_names(Some(HashMap::from([("#status".into(), "status".into())])))
        .set_expression_attribute_values(Some(HashMap::from([(":val".into(), filter_val.into())])))
        .send()
        .await
        .map(|_| ())
        .map_err(|e| e.to_string())
}

By combining strict CORS, fixed table usage, least-privilege IAM, and input validation, the Actix service becomes resilient to DNS rebinding attempts that target DynamoDB endpoints. middleBrick can verify these protections by scanning the exposed API surface and ensuring that no endpoint reflects untrusted origins or exposes internal resource names.

Frequently Asked Questions

Can DNS rebinding bypass CORS in Actix apps?
CORS restricts browser-based origins, but if an Actix endpoint does not validate origin and is reachable from a malicious page, a rebinding attack can still force the browser to make requests that the server honors. Always enforce strict CORS and avoid trusting request origins implicitly.
Does DynamoDB itself prevent rebinding misuse?
DynamoDB enforces IAM policies and does not directly prevent rebinding; the protection depends on the calling service. If an Actix service is tricked into making privileged calls, DynamoDB will process them as allowed by the credentials used. Therefore, secure the service layer with origin checks and least-privilege permissions.