Bola Idor in Axum with Basic Auth
Bola Idor in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability
Broken Object Level Authorization (BOLA) occurs when an API fails to enforce authorization checks such that one object can be accessed simply by changing its identifier. In Axum, this commonly maps to route parameters or path-based identifiers that are used to look up a resource without confirming that the requesting user has permission to view or modify that specific object. When Basic Auth is used, the server validates the presence of a username/password pair but may stop there, implicitly trusting the authenticated identity without checking whether the authenticated subject is allowed to access the particular resource identified in the request.
Consider an endpoint like GET /users/{user_id} where Axum extracts user_id from the path and queries a database. With Basic Auth, the server decodes the Authorization header, retrieves the user record for the provided credentials, and may return the requested user_id without confirming that the authenticated user’s ID matches the requested user_id. This creates a BOLA condition: authentication is present, but authorization is missing or misapplied. An attacker who can obtain or guess another user’s ID can read or act on that resource simply by supplying valid Basic Auth credentials for their own account. This is a classic vertical or horizontal privilege escalation depending on whether the attacker targets another user or an admin account.
The interaction with Basic Auth is subtle but important. Basic Auth transmits credentials on each request (base64-encoded, not encrypted), so if the channel is not protected by TLS, credentials are easily exposed. Even when TLS is used, the server must still enforce object-level checks. Relying on path-based identifiers without scoping them to the authenticated identity means that the authentication layer and the authorization layer are not bound together. In Axum, this often manifests as a handler that uses something like user_id: u64 to fetch a record, without comparing that ID to the user ID extracted from the authentication context. The scan may flag this as a BOLA risk because the endpoint is unauthenticated-surface tested, and the presence of Basic Auth does not automatically imply proper scoping.
Real-world analogies include IDOR in REST APIs where numeric keys are incremented. If /accounts/123 returns data when authenticated with valid Basic Auth, an attacker can try /accounts/124 to see if the server returns another account. This pattern is also relevant to GraphQL and other query mechanisms where object references are exposed. The risk is elevated when identifiers are predictable, and the API does not enforce a consistent authorization policy across all endpoints.
middleBrick’s checks for BOLA include runtime testing against endpoints with different object identifiers while using the same authenticated context (in this case, Basic Auth). If the score shows findings in the Authorization category, it indicates that object-level boundaries are not reliably enforced. The scan does not change, block, or remediate; it surfaces the condition so that developers can apply proper scoping and policy checks.
Basic Auth-Specific Remediation in Axum — concrete code fixes
To fix BOLA with Basic Auth in Axum, you must explicitly scope every data access to the authenticated subject. Do not rely on path parameters alone; derive the authorized subject from the authentication context and compare it to the requested identifier before querying the store.
Below is a minimal, realistic Axum handler pattern that demonstrates correct authorization alongside Basic Auth extraction. It uses tower-http for Basic Auth extraction and a custom extractor that provides the authenticated user’s ID to handlers.
use axum::{
async_trait, extract::FromRequest, http::StatusCode, response::IntoResponse, routing::get,
Router,
};
use tower_http::auth::{AuthBackend, AuthRequest, BasicAuthLayer};
use std::net::SocketAddr;
// Domain types
struct UserId(u64);
struct User { id: UserId, username: String }
// A custom extractor that requires authentication and exposes the user ID.
#[derive(Debug, Clone)]
struct AuthedUser(User);
#[async_trait]
impl FromRequest<S> for AuthedUser
where
S: Send + Sync,
{
type Rejection = (StatusCode, &'static str);
async fn from_request(req: axum::extract::Request) -> Result<Self, Self::Rejection> {
// In a real app, you would validate the credentials against a database.
// Here we assume tower-http has already validated Basic Auth and placed
// the identity into request extensions (or you can implement your own AuthBackend).
req.extensions()
.get::
The key remediation steps are:
- Extract authentication (e.g., via
tower-http::author a custom middleware) and place the user identity into request extensions or a custom extractor. - In each handler that accepts an object identifier (path parameter, query param, or body reference), compare that identifier to the authenticated subject’s ID. Reject with 403 if they do not match.
- Use the authenticated subject as a scope filter in database queries (e.g.,
SELECT * FROM users WHERE id = $1 AND owner_id = $2) rather than trusting the client-supplied ID alone. - Always serve Basic Auth over TLS to protect credentials in transit.
By coupling authentication with explicit authorization checks, you eliminate the BOLA vector even when Basic Auth is used. middleBrick can then verify that these scoping checks are present and correctly applied during its runtime scan.
Related CWEs: bolaAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-250 | Execution with Unnecessary Privileges | HIGH |
| CWE-639 | Insecure Direct Object Reference | CRITICAL |
| CWE-732 | Incorrect Permission Assignment | HIGH |