Phishing Api Keys in Axum with Basic Auth
Phishing API Keys in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability
When an Axum service uses HTTP Basic Auth without additional transport protections, API keys can be phished through multiple vectors. Basic Auth encodes credentials with Base64, which is reversible and provides no encryption in transit. If a client application embeds an API key as the password in the Authorization header, a phishing site or malicious proxy can trivially intercept and decode the token. MiddleBrick’s unauthenticated scan tests this by probing endpoints that accept Basic Auth and checking whether credentials are transmitted over non-TLS channels and whether the API key is discoverable in logs, error messages, or predictable resource paths.
In Axum, handlers often parse the Authorization header manually or via middleware. Consider a naive extractor that reads the header and splits on ‘:’ to obtain a key:
use axum::{headers::authorization::Authorization, http::HeaderMap};
fn extract_key(headers: &HeaderMap) -> Option<String> {
let auth = headers.get::
If the decoded segment contains an API key, and the response or logs inadvertently expose it (e.g., through detailed error responses or structured logging), the key can be phished. The scan checks whether responses include stack traces or validation messages that reveal whether a provided token was valid, a common step in credential harvesting. Additionally, if the same API key is reused across services or stored in client-side JavaScript, a phishing site that lures a user can leverage that key to call the Axum endpoint on behalf of the victim.
Another phishing path arises from insecure OpenAPI/Swagger exposure. If an Axum service publishes a spec containing example values with real API keys, and that spec is accessible without authentication, a scanner can extract the key directly. MiddleBrick’s OpenAPI analysis resolves $ref chains and cross-references definitions with runtime findings to detect such accidental exposure. The LLM/AI Security checks further probe whether an endpoint serving a spec can be tricked into leaking system prompts or sensitive metadata via prompt injection techniques, which could include references to internal API keys.
Because Basic Auth does not rotate by itself and keys are often long-lived, reused credentials increase the impact of a successful phishing attack. The scanner evaluates whether rate limiting is present to deter brute-force attempts and whether data exposure findings indicate that credentials are echoed back in responses. Prioritized remediation guidance is provided, emphasizing transport security, token binding, and avoiding embedding keys in client-side code.
Basic Auth-Specific Remediation in Axum — concrete code fixes
To mitigate phishing of API keys in Axum when using Basic Auth, enforce strict transport security and avoid embedding keys in reversible credentials. Always serve endpoints over HTTPS and prefer opaque bearer tokens or structured authentication schemes that do not expose secrets in headers. When Basic Auth is required for compatibility, ensure the password field is a one-time token or a hash, and never a raw API key.
Use middleware to validate the presence of TLS and to strip or mask sensitive headers in logs. The following example shows a secure Axum handler that requires TLS and uses a constant-time comparison to avoid timing attacks:
use axum::{{
extract::Extension,
http::HeaderMap,
response::IntoResponse,
routing::get,
Router,
}};
use std::net::SocketAddr;
use tokio_rustls::TlsAcceptor;
async fn secure_handler(headers: HeaderMap) -> impl IntoResponse {
// Enforce TLS at the handler level as an additional safeguard
// In practice, enforce TLS at the load balancer or middleware
let api_key = headers.get("X-API-Key").and_then(|v| v.to_str().ok());
match api_key {
Some(key) if validate_key(key) => "OK",
_ => (axum::http::StatusCode::UNAUTHORIZED, "Invalid credentials"),
}
}
fn validate_key(candidate: &str) -> bool {
// Use constant-time comparison to avoid timing leaks
let expected = std::env::var("API_KEY").unwrap_or_default();
subtle::ConstantTimeEq::ct_eq(candidate.as_bytes(), expected.as_bytes()).into()
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/secure", get(secure_handler));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
Alternatively, adopt a token-based approach where the client presents a short-lived JWT instead of a Basic Auth password. If Basic Auth must be retained, rotate the password frequently and avoid including the API key itself in the decoded value. MiddleBrick’s CLI can be used to verify these changes:
middlebrick scan https://api.example.com/v1/openapi.json
Using the GitHub Action, you can fail builds when a scan detects exposed API keys in specs or responses. The MCP Server allows you to run scans directly from your IDE while developing Axum routes, helping catch risky patterns before deployment.
Finally, ensure that any logging in Axum filters out Authorization headers and API keys. Structured logging should redact sensitive fields, and error responses should be generic to prevent attackers from probing valid credentials through differential behavior.