Privilege Escalation in Actix with Bearer Tokens
Privilege Escalation in Actix with Bearer Tokens — how this combination creates or exposes the vulnerability
In Actix web applications, Bearer tokens are commonly used for authorization via HTTP Authorization headers. Privilege escalation occurs when a lower-privilege identity can access a higher-privilege endpoint because token validation is incomplete or bypassed. This can happen when middleware checks only the presence of a token and not the scopes or roles encoded in it, or when tokens are accepted from unexpected sources (e.g., URL parameters or cookies) instead of strictly the Authorization header.
For example, an endpoint intended for administrators might rely on a token claim such as role: admin. If the Actix handler or guard does not validate that claim, a user with a token containing role: user can reach the admin route and perform privileged actions. In a black-box scan, middleBrick tests this by submitting the same request with a low-privilege token and a missing token to see whether the endpoint behaves differently, exposing BOLA/IDOR or privilege escalation paths.
Real-world attack patterns mirror this: attackers enumerate administrative routes, then attempt access with a token lacking admin privileges. If the application trusts token format but not token content, this becomes a straightforward privilege escalation. The risk is compounded when token introspection or validation is inconsistent across routes, or when development shortcuts (such as permissive CORS or relaxed guards) are left in production. OWASP API Top 10 2023’s Broken Object Level Authorization (BOLA) and the broader category of Improper Authorization map directly to these scenarios.
middleBrick’s LLM/AI Security checks do not apply here, but its authorization and property authorization tests validate whether a token’s claims are enforced. By running parallel checks, the scanner can identify cases where endpoints accept tokens but ignore embedded role or scope claims, surfacing the need for claim-based guards rather than mere presence checks.
Bearer Tokens-Specific Remediation in Actix — concrete code fixes
Remediation focuses on validating token content and enforcing least privilege. In Actix, extract the token from the Authorization header, verify its signature and claims, and use guard checks that inspect roles or scopes before allowing access.
Example: Validating a Bearer token and checking a role claim
use actix_web::{web, HttpRequest, HttpResponse, Error};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, TokenData};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
role: String,
exp: usize,
}
async fn validate_bearer(req: &HttpRequest) -> Result, Error> {
let auth_header = req.headers().get("Authorization");
let header_value = auth_header.ok_or(actix_web::error::ErrorUnauthorized("missing authorization header"))?;
let header_str = header_value.to_str().map_err(|_| actix_web::error::ErrorUnauthorized("invalid authorization header"))?;
if !header_str.starts_with("Bearer ") {
return Err(actix_web::error::ErrorUnauthorized("invalid authorization scheme"));
}
let token = header_str.trim_start_matches("Bearer ");
let decoding_key = DecodingKey::from_secret("YOUR_SECRET_KEY".as_ref());
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = true;
let token_data = decode::(token, &decoding_key, &validation)
.map_err(|_| actix_web::error::ErrorUnauthorized("invalid token"))?;
Ok(token_data)
}
async fn admin_handler(req: HttpRequest) -> HttpResponse {
match validate_bearer(&req).await {
Ok(token_data) => {
if token_data.claims.role != "admin" {
return HttpResponse::Forbidden().body("insufficient privileges");
}
HttpResponse::Ok().body("admin action executed")
}
Err(e) => HttpResponse::Unauthorized().body(format!("unauthorized: {:?}", e)),
}
}
This example ensures the token is extracted strictly from the Authorization header, verifies the signature, checks expiration, and enforces a role claim. It avoids accepting tokens from query strings or cookies, which reduces the attack surface for token smuggling and privilege escalation.
Example: Scoped token validation for least privilege
use actix_web::{web, HttpRequest, HttpResponse, Error};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, TokenData};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
scope: String,
exp: usize,
}
async fn validate_scoped_token(req: &HttpRequest, required_scope: &str) -> Result, Error> {
let auth_header = req.headers().get("Authorization")
.ok_or(actix_web::error::ErrorUnauthorized("missing authorization header"))?;
let header_str = auth_header.to_str().map_err(|_| actix_web::error::ErrorUnauthorized("invalid header"))?;
if !header_str.starts_with("Bearer ") {
return Err(actix_web::error::ErrorUnauthorized("invalid authorization scheme"));
}
let token = header_str.trim_start_matches("Bearer ");
let decoding_key = DecodingKey::from_secret("YOUR_SECRET_KEY".as_ref());
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = true;
let token_data = decode::(token, &decoding_key, &validation)
.map_err(|_| actix_web::error::ErrorUnauthorized("invalid token"))?;
if token_data.scope != required_scope {
return Err(actix_web::error::ErrorForbidden("insufficient scope"));
}
Ok(token_data)
}
async fn billing_handler(req: HttpRequest) -> HttpResponse {
match validate_scoped_token(&req, "billing:read").await {
Ok(_) => HttpResponse::Ok().body("billing data"),
Err(e) => HttpResponse::Unauthorized().body(format!("unauthorized: {:?}", e)),
}
}
By tying permissions to claims and scopes, these patterns ensure that a token’s mere presence does not grant elevated rights. middleBrick’s CLI can be used to verify that endpoints reject requests with insufficient-scope tokens, and the Pro plan’s continuous monitoring can alert you if new routes lack proper claim checks.
When integrating with identity providers, always prefer tokens issued with minimal scopes and short lifetimes. Combine this with Actix guards that inspect claims rather than relying on route-level allowlists. The GitHub Action can enforce that new endpoints include authorization checks before merge, reducing the likelihood of accidental privilege escalation after changes.