Insecure Direct Object Reference in Actix with Mutual Tls
Insecure Direct Object Reference in Actix with Mutual Tls
Insecure Direct Object Reference (BOLA/IDOR) occurs when an API exposes internal object identifiers (e.g., numeric IDs, UUIDs) without verifying that the requesting actor has permission to access that specific resource. In Actix web applications using mutual TLS (mTLS), the presence of client certificates for authentication can create a false sense of security. Developers may assume that mTLS alone is sufficient for authorization, but mTLS only binds a certificate to an identity; it does not enforce object-level permissions. An authenticated client with a valid certificate can still modify or access URLs like /users/123 and /users/124 if the server does not explicitly check whether that client is allowed to interact with the targeted resource.
Consider an Actix service that retrieves user profiles using a path parameter:
async fn get_user_profile(user_id: web::Path, req: HttpRequest) -> impl Responder { let requester_id = get_requester_id_from_mtls_cert(&req); // extracts subject from client cert // BOLA/IDOR risk: no check that requester_id owns user_id match User::find(*user_id) { Some(user) => HttpResponse::Ok().json(user), None => HttpResponse::NotFound().finish(), } }
Even with mTLS, if requester_id is not compared to the owning user of the requested user_id, an attacker who possesses a valid client certificate can enumerate user IDs and access other users’ data. This is a classic BOLA/IDOR vulnerability in the unauthenticated (black-box) attack surface tested by middleBrick, where the scanner submits requests with valid mTLS client certs but varies object identifiers to detect insecure references.
Another common pattern is using opaque references (e.g., UUIDs) that are predictable or not mapped to access control lists. For example:
async fn get_document(doc_ref: web::Path, req: HttpRequest) -> impl Responder { let user_cert_subject = extract_subject(&req); let doc = DocumentRepository::get_by_ref(&doc_ref); // BOLA/IDOR: doc may belong to another tenant or user; no tenant ownership check HttpResponse::Ok().json(doc) }
Here, the server retrieves a document by reference but does not verify that the mTLS-authenticated user’s tenant or role is allowed to access that document. middleBrick’s BOLA/IDOR checks include attempting to access known resource patterns with different identifiers while using the same mTLS credentials, looking for unauthorized data exposure or modification paths.
Because Actix routes often bind parameters directly to handler arguments, it is easy to omit authorization checks. mTLS provides transport-layer client authentication but does not replace application-level ownership verification. To detect this, middleBrick runs multiple probes with valid mTLS client certs targeting sequential or guessed identifiers and inspects responses for differences that indicate insecure references.
Mutual Tls-Specific Remediation in Actix
Remediation requires combining mTLS-based identity extraction with explicit object-level authorization. In Actix, you should resolve the mTLS client certificate to a principal (e.g., user ID or tenant) and then enforce that principal’s permissions on the requested resource before returning any data.
Below is a concrete, secure pattern using the openssl-based mTLS setup in Actix, where the client certificate subject is mapped to a user and checked against the requested resource:
use actix_web::{web, HttpRequest, Responder, HttpResponse};
use openssl::x509::X509;
fn get_requester_id_from_cert(cert: &X509) -> Option {
// extract subject common name or a custom OID as the identity
cert.subject_name()
.entries()
.find(|e| e.object().to_string() == "2.5.4.3") // common name OID
.and_then(|e| e.data().as_utf8_string().ok())
.map(|s| s.to_string())
}
async fn get_user_profile(
user_id: web::Path,
req: HttpRequest,
) -> impl Responder {
// Extract client certificate from request extensions (configured via .ssl())
let cert = match req.extensions().get::() {
Some(c) => c,
None => return HttpResponse::Unauthorized().finish(),
};
let requester_id = match get_requester_id_from_cert(cert) {
Some(id) => id,
None => return HttpResponse::Unauthorized().finish(),
};
// Enforce BOLA/IDOR: ensure the requester is allowed to view this user
if !UserPolicy::can_view(&requester_id, *user_id) {
return HttpResponse::Forbidden().finish();
}
match User::find(*user_id) {
Some(user) => HttpResponse::Ok().json(user),
None => HttpResponse::NotFound().finish(),
}
}
In this example, UserPolicy::can_view implements the application-specific authorization rule (e.g., users can only view their own profile, or members of a group can access shared documents). This check must always be performed regardless of mTLS validity.
For document-like resources referenced by non-sequential identifiers:
async fn get_document(
doc_ref: web::Path,
req: HttpRequest,
) -> impl Responder {
let cert = match req.extensions().get::() {
Some(c) => c,
None => return HttpResponse::Unauthorized().finish(),
};
let requester_tenant = match get_tenant_from_cert(cert) {
Some(t) => t,
None => return HttpResponse::Unauthorized().finish(),
};
// Enforce tenant-level BOLA/IDOR
let doc = match DocumentRepository::get_by_ref_and_tenant(&doc_ref, &requester_tenant) {
Some(d) => d,
None => return HttpResponse::NotFound().finish(),
};
HttpResponse::Ok().json(doc)
}
These patterns ensure that mTLS is used for authentication while explicit checks handle authorization. middleBrick’s scans validate that such checks exist by probing endpoints with different object identifiers under the same mTLS identity and looking for missing authorization responses or data leakage.
Additionally, configure Actix TLS with client verification to ensure mTLS is properly enforced at the transport layer. The server-side SSL configuration should request and validate client certificates, but application code must still perform resource-level authorization as shown above.
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 |