Clickjacking in Axum with Basic Auth
Clickjacking in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side attack where an attacker tricks a user into interacting with invisible or disguised UI elements inside an embedded frame. When Basic Authentication is used in an Axum application, the browser typically caches credentials after the first challenge and may send them automatically in subsequent requests, even when the page is loaded inside a malicious site via an iframe. This means a clickjacked UI can cause the browser to perform authenticated actions on behalf of the user without their awareness, combining UI deception with HTTP authentication semantics.
Consider an Axum endpoint that performs a sensitive operation (for example, changing an email address) via a POST request. If this endpoint does not enforce frame-embedding restrictions and relies solely on Basic Auth for access control, an attacker can embed the endpoint URL inside an iframe on a phishing page. When a victim visits the attacker’s page, the browser may send the Basic Auth credentials automatically, and user interactions such as clicking a benign button can trigger the sensitive POST action inside the hidden frame. Because the response is often displayed inside the frame, the user may see a benign page while the unauthorized action completes in the background.
Another dimension involves the use of inline frames with partial or full page overlays. Even if the target endpoint includes standard security headers elsewhere, missing Content-Security-Policy frame-ancestors rules or X-Frame-Options allows embedding. Basic Auth does not prevent this embedding; it only provides a transport-layer credential mechanism. Therefore, the combination of a permissive framing policy and Basic Auth can expose authenticated actions to clickjacking, making it essential to apply frame-protection controls explicitly in Axum handlers.
Basic Auth-Specific Remediation in Axum — concrete code fixes
To mitigate clickjacking in Axum while using Basic Auth, you must enforce frame-embedding restrictions and ensure credentials are not automatically sent to embedded contexts. The primary defenses are Content-Security-Policy frame-ancestors and, where supported, X-Frame-Options. CSP frame-ancestors is the modern mechanism and should be preferred.
Below is a concrete Axum example that adds these headers to responses. It demonstrates how to protect endpoints that rely on Basic Auth by preventing them from being embedded in frames, while preserving legitimate usage when your application embeds its own resources.
use axum::{
async_trait,
extract::FromRequest,
http::{Request, StatusCode, HeaderMap, HeaderValue},
response::{IntoResponse, Response},
};
use std::convert::Infallible;
/// A middleware layer that adds security headers including CSP frame-ancestors
/// and X-Frame-Options to prevent clickjacking.
pub async fn add_security_headers(mut response: Response) -> Response {
let headers = response.headers_mut();
// Prevent embedding in any frame, regardless of origin
headers.insert(
"Content-Security-Policy",
HeaderValue::from_static("frame-ancestors 'none'"),
);
// Extra defense for older browsers that do not support CSP frame-ancestors
headers.insert(
"X-Frame-Options",
HeaderValue::from_static("DENY"),
);
response
}
/// Example protected route using Basic Auth and security headers.
async fn sensitive_operation() -> impl IntoResponse {
// Perform the sensitive action here
(StatusCode::OK, "Action completed securely")
}
/// Apply the header middleware to your routes.
/// In a real app, you would integrate this via `tower::ServiceBuilder` or `axum::middleware::from_fn`.
async fn handler_with_security_headers(request: Request) -> Response {
// You would normally validate Basic Auth credentials here.
// For brevity, we focus on header injection.
let response = sensitive_operation().await.into_response();
add_security_headers(response).await
}
These headers instruct browsers to refuse to render the page in a frame, effectively neutralizing clickjacking attempts. Note that middleware placement matters: the security headers must be applied after authentication so that protected endpoints are covered. If you serve public pages that legitimately embed content, adjust frame-ancestors to a controlled list of sources (for example, frame-ancestors 'self';) instead of 'none'.
Additionally, ensure that Basic Auth is transmitted only over HTTPS to prevent credential leakage, as clickjacking defenses do not protect credentials in transit. Combining HTTPS, strict frame-ancestors policies, and X-Frame-Options provides robust protection for authenticated endpoints in Axum.