Missing Tls in Axum
How Missing Tls Manifests in Axum
Missing TLS in Axum applications creates several critical attack vectors that directly impact API security. When Axum endpoints are exposed over HTTP instead of HTTPS, attackers can intercept authentication tokens, session cookies, and API keys transmitted between clients and servers. This is particularly dangerous for Axum applications handling sensitive data like user credentials, financial information, or personal health records.
Axum's routing system makes it easy to accidentally expose endpoints without proper TLS enforcement. For example, developers might create routes like:
let app = Router::new()
.route("/api/users", get(get_users))
.route("/api/auth/login", post(login));When deployed without TLS termination, these endpoints transmit data in plaintext. Attackers on the same network can use tools like Wireshark or tcpdump to capture traffic and extract sensitive information. The problem compounds when Axum applications run behind reverse proxies that don't properly enforce HTTPS redirection.
Another manifestation occurs with Axum's middleware chain. Developers might add authentication middleware that assumes HTTPS is already in place:
let auth = auth::Auth::new().excluded_routes(vec!["/health"]);
let app = Router::new()
.layer(auth)
.route("/api/*", get(api_handler));Without TLS, authentication tokens sent to these endpoints are vulnerable to interception. Man-in-the-middle attackers can steal session cookies, replay authentication requests, or modify API responses to inject malicious content.
API keys and bearer tokens transmitted over HTTP are especially problematic in Axum applications. Consider this endpoint:
async fn create_order(
Extension(auth): Extension,
Json(payload): Json<CreateOrder>,
) -> Result<Json<Order>> { ... } Without TLS, the entire request including the Authorization header travels unencrypted. Attackers can capture these requests and use stolen credentials to access other APIs or services that share authentication mechanisms.
Axum-Specific Detection
Detecting missing TLS in Axum applications requires both runtime scanning and static analysis. middleBrick's API security scanner specifically identifies TLS configuration issues in Axum applications by examining endpoint behavior and response headers.
The scanner tests whether Axum endpoints properly redirect HTTP to HTTPS and whether they include security headers like Strict-Transport-Security (HSTS). For Axum applications, missing TLS manifests as:
- Endpoints responding on port 80 instead of 443
- Missing HSTS headers in responses
- No HTTP-to-HTTPS redirection
- API endpoints accessible without encryption
middleBrick's scanning process for Axum applications includes these specific checks:
$ middlebrick scan https://api.example.com
=== TLS Configuration ===
✅ Certificate valid
✅ TLS 1.3 supported
❌ HTTP endpoint accessible (port 80)
❌ Missing HSTS header
❌ No HTTP-to-HTTPS redirectFor development environments, Axum developers can use middleware to enforce TLS requirements:
use axum_extra::middleware::Next;async fn require_https(mut req: Request, next: Next) -> Result<Response> { if let Some(addr) = req.headers().get("host") { if addr.to_string().starts_with("http://") { return Ok(Response::builder()
.status(StatusCode::MOVED_PERMANENTLY)
.header("Location", addr.to_string().replace("http://", "https://"))
.body(Body::empty())
.unwrap()); } } next.run(req).await } let app = Router::new()
.route("/api/*", get(api_handler))
.layer(tower_http::trace::TraceLayer::new_for_http())
.layer(tower::layer::LayerFunc::new(require_https));middleBrick's scanner also detects configuration issues in Axum applications deployed behind reverse proxies. It verifies that the X-Forwarded-Proto header is properly trusted and that the proxy correctly terminates TLS before passing requests to Axum.
Axum-Specific Remediation
Securing Axum applications against missing TLS requires both configuration changes and code modifications. The most effective approach combines proper deployment practices with Axum-specific middleware.
First, ensure your Axum application only binds to HTTPS ports. Modify your main function to enforce TLS:
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::routing::get;
use axum::Router;
use axum::Server;
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(index))
.route("/api/*", get(api_handler));
// TLS configuration
let listener = TcpListener::bind("0.0.0.0:443").await.unwrap();
let config = axum::http::server::TlsConfig::new()
.key_path("path/to/key.pem")
.cert_path("path/to/cert.pem");
Server::with_listener(listener)
.tls_config(config)
.unwrap()
.serve(app.into_make_service())
.await
.unwrap();
}For applications behind reverse proxies, use Axum's trusted header middleware:
use tower_http::cors::CorsLayer;
use tower_http::set_header::SetRequestHeaderLayer;
use tower_http::validate_request::ValidateRequestHeaderLayer;
let app = Router::new()
.route("/api/*", get(api_handler))
.layer(ValidateRequestHeaderLayer::builder(
"x-forwarded-proto",
|val| val == "https",
).with_cause())
.layer(SetRequestHeaderLayer::if_not_present(
"strict-transport-security",
"max-age=31536000; includeSubDomains",
));middleBrick's scanner validates these configurations and provides specific remediation guidance. For example, if HSTS headers are missing, it recommends:
let hsts_layer = SetResponseHeaderLayer::overriding(
"strict-transport-security",
"max-age=31536000; includeSubDomains; preload",
);
let app = app.layer(hsts_layer);Another critical remediation is implementing proper HTTP-to-HTTPS redirection. Axum provides middleware for this:
use axum::http::uri::Uri;
use axum::middleware::Next;
use axum::response::IntoResponse;
use axum::routing::get;
use axum::Router;
use http::HeaderValue;
async fn redirect_https(mut req: Request, next: Next) -> Result<Response> {
let uri = req.uri();
if uri.scheme() == Some(&http::uri::Scheme::HTTP) {
let https_uri = Uri::builder()
.scheme(http::uri::Scheme::HTTPS)
.authority(uri.authority().unwrap())
.path_and_query(uri.path_and_query().unwrap())
.build()
.unwrap();
let mut res = Response::new(Body::empty());
*res.status_mut() = StatusCode::MOVED_PERMANENTLY;
res.headers_mut()
.insert("location", HeaderValue::from_str(https_uri.to_string().as_str()).unwrap());
return Ok(res);
}
next.run(req).await
}
let app = Router::new()
.route("/", get(index))
.layer(tower::layer::LayerFunc::new(redirect_https));middleBrick's continuous monitoring in Pro tier helps ensure these TLS configurations remain intact across deployments and environment changes.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |