Dns Rebinding in Axum with Basic Auth
Dns Rebinding in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability
DNS rebinding is a client-side attack where a malicious webpage resolves to a seemingly internal IP address (e.g., 127.0.0.1 or a corporate IP) after the initial DNS lookup, enabling a browser to bypass same-origin policy and reach internal services. When Basic Auth is used in an Axum service without additional protections, the browser may automatically send the credentials during the rebinding request because the target host and port match the protected origin. This can cause authenticated requests to be issued from the victim’s browser to internal endpoints that were not intended to be exposed over the public internet.
In Axum, if an endpoint relies solely on Basic Auth for access control and does not implement defenses such as strict origin validation or anti-rebinding headers, an attacker who can trick a user into visiting a malicious site may cause the user’s browser to make authenticated requests to internal IPs or localhost. Because the request includes valid credentials, Axum may process the request as authorized, potentially exposing administrative or diagnostic endpoints. This becomes especially dangerous when combined with other unchecked attack surfaces such as unauthenticated LLM endpoints or insecure runtime introspection paths that might be reachable via rebinding.
Consider an Axum service that uses Basic Auth middleware and exposes a debug endpoint at /debug/pprof on the same host as a public API. If an API consumer’s browser is tricked into resolving the public hostname to 127.0.0.1 (via DNS rebinding), the browser will send the stored Basic Auth credentials to the debug endpoint. Because the credentials are valid, the endpoint may respond with sensitive runtime information, effectively bypassing network segregation. MiddleBrick scans detect such exposed endpoints and unsafe consumption patterns by correlating spec definitions with runtime behavior, flagging routes that accept authenticated traffic without sufficient boundary checks.
Basic Auth-Specific Remediation in Axum — concrete code fixes
To mitigate DNS rebinding risks when using Basic Auth in Axum, you should combine credential validation with network-level and application-level controls. Always validate the Host header and enforce strict origin checks on incoming requests. Do not rely on Basic Auth alone to protect sensitive endpoints; treat it as a transport-level mechanism and layer it with other guards.
Below are concrete Axum examples that demonstrate secure handling of Basic Auth alongside origin validation and route protection.
use axum::{
async_trait, extract::Request, http::header, routing::get, Router,
response::IntoResponse,
};
use std::net::{IpAddr, Ipv4Addr};
/// Allowed origins for requests. In production, make this configurable and tightly scoped.
const ALLOWED_ORIGIN: &str = "https://api.example.com";
/// Validate Host header to prevent DNS rebinding to internal IPs.
fn is_valid_host(host: &str) -> bool {
// Define allowed hosts and resolved IPs.
let allowed_hosts = ["api.example.com", "app.example.com"];
let allowed_ips = [IpAddr::V4(Ipv4Addr::new(203, 0, 113, 10))];
allowed_hosts.contains(&host) || allowed_ips.contains(&host.parse().ok()?)
}
/// Validate Origin header to mitigate DNS rebinding.
fn validate_origin(req: &Request) -> bool {
if let Some(origin) = req.headers().get(header::ORIGIN) {
if let Ok(origin_str) = origin.to_str() {
return origin_str == ALLOWED_ORIGIN;
}
}
false
}
async fn debug_public_info() -> impl IntoResponse {
(axum::http::StatusCode::OK, "Public debug info")
}
async fn protected_route() -> impl IntoResponse {
(axum::http::StatusCode::OK, "Protected data")
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/debug/public", get(debug_public_info))
.route("/api/protected", get(protected_route))
.layer(axum::middleware::from_fn(async |req, next| {
// Reject requests with missing or mismatched Host.
let host = req.headers()
.get(header::HOST)
.and_then(|h| h.to_str().ok())
.unwrap_or("");
if !is_valid_host(host) {
return Ok::<_, axum::BoxError>(
(axum::http::StatusCode::FORBIDDEN, "Invalid host").into_response(),
);
}
// Enforce strict Origin validation for credentialed routes.
if !validate_origin(&req) {
return Ok::<_, axum::BoxError>(
(axum::http::StatusCode::FORBIDDEN, "Invalid origin").into_response(),
);
}
// Proceed to Basic Auth extraction and verification.
let auth_header = req.headers()
.get(header::AUTHORIZATION)
.and_then(|h| h.to_str().ok())
.unwrap_or("");
if !verify_basic_auth(auth_header) {
let response = (axum::http::StatusCode::UNAUTHORIZED,
[(header::WWW_AUTHENTICATE, "Basic realm=\"secure\"")]
).into_response();
return Ok(response);
}
let response = next.run(req).await?;
Ok(response)
}));
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
fn verify_basic_auth(header_value: &str) -> bool {
// In real services, decode and compare against a secure store.
const EXPECTED_USER: &str = "admin";
const EXPECTED_PASS: &str = "s3cur3pass";
if let Ok(auth) = base64::decode(header_value.trim_start_matches("Basic ")) {
if let Ok(credentials) = String::from_utf8(auth) {
let parts: Vec<&str> = credentials.splitn(2, ':').collect();
return parts.get(0) == Some(&EXPECTED_USER) && parts.get(1) == Some(&EXPECTED_PASS);
}
}
false
}
Key mitigations in this pattern:
- Host validation prevents the server from accepting requests where the Host header resolves to an internal IP, reducing the effectiveness of DNS rebinding.
- Strict Origin checking ensures that credentialed requests originate only from approved domains, blocking cross-origin rebinding attempts from malicious sites.
- Basic Auth is verified only after network and origin checks, ensuring that even if credentials are sent, they are not honored for suspicious origins.
- Expose minimal endpoints over public interfaces; avoid binding debug or introspection routes to the same host and port as authenticated APIs unless they are rigorously guarded.
In addition to code controls, use network design practices such as binding sensitive endpoints to localhost or internal networks only, employing reverse proxy ACLs, and avoiding Basic Auth for high-risk operations without additional context-aware checks. MiddleBrick’s scans highlight routes that lack such layered protections and map findings to frameworks like OWASP API Top 10 and PCI-DSS to support remediation planning.