HIGH bola idorrocket

Bola Idor in Rocket

How Bola Idor Manifests in Rocket

BOLA/IdOR (Broken Object Level Authorization/Insecure Direct Object Reference) vulnerabilities in Rocket occur when the framework's request handling allows users to access or modify resources belonging to other users by manipulating object identifiers in API requests. Rocket's flexible routing system and parameter extraction can inadvertently expose these weaknesses if authorization checks are not properly implemented.

The most common manifestation appears in Rocket's dynamic route parameters. Consider a typical user profile endpoint:

#[get("/users//profile")]
pub fn get_user_profile(id: i32) -> &'static str {
    // No authorization check - any user can access any profile
    format!("Profile for user {}", id).as_str()
}

This pattern is dangerous because Rocket's <id> parameter extraction automatically converts the URL segment to an integer without any ownership validation. An authenticated user can simply change the ID value to access other users' data.

Resource manipulation endpoints are equally vulnerable. In a file upload system:

#[post("/upload/", data = "<data>")]
pub fn upload_file(user_id: i32, data: Data) -> &'static str {
    // No check that user_id matches authenticated user
    let path = format!("/uploads/{}.txt", user_id);
    data.stream_to_file(path).unwrap();
    "Upload successful"
}

Here, any authenticated user can upload files to any user's directory by manipulating the user_id parameter. Rocket's type-safe parameter extraction makes this particularly insidious - the code compiles and runs without any obvious errors.

Database query patterns in Rocket applications often compound the problem. Using Rocket's request guards with Diesel or other ORMs:

#[get("/posts/")]
pub fn get_post(post_id: i32, db: DbConn) -> Json<Post> {
    use schema::posts::dsl::*;
    let post = posts.find(post_id).first(&db.0).unwrap();
    Json(post)
}

This directly queries by ID without verifying the authenticated user's ownership. The database returns whatever record matches the ID, regardless of who should have access.

Rocket's JSON deserialization can also introduce BOLA vulnerabilities when handling nested objects:

#[derive(Deserialize)]
struct UpdateRequest {
    user_id: i32,
    email: String,
    // ... other fields
}

#[put("/update-profile")]
pub fn update_profile(req: Json<UpdateRequest>) -> &'static str {
    // User could set user_id to another user's ID
    update_user(req.user_id, req.email.clone()).unwrap();
    "Profile updated"
}

The deserialization process trusts client-provided data, allowing attackers to modify the user_id field to target other accounts.

Rocket-Specific Detection

Detecting BOLA/IdOR vulnerabilities in Rocket applications requires systematic analysis of route handlers and their authorization logic. The most effective approach combines static code analysis with runtime scanning.

Static analysis should focus on Rocket's route attribute patterns. Look for routes with dynamic parameters that access user-specific resources:

#[get("/api/v1/users//data")]
#[get("/api/v1/orders/")]
#[put("/api/v1/profiles/")]

Each of these patterns warrants investigation. The presence of <id> parameters in routes that access user data is a red flag.

middleBrick's scanning approach specifically targets these Rocket patterns. The scanner analyzes the OpenAPI spec generated from Rocket's route structure, then performs active testing by manipulating ID parameters across endpoints. For Rocket applications, middleBrick:

  • Extracts all dynamic route parameters from Rocket's route table
  • Identifies resource access patterns based on parameter names and path structures
  • Performs automated ID manipulation testing across authenticated endpoints
  • Cross-references findings with authentication state to detect unauthorized access

The scanner's LLM security module also checks for AI-specific BOLA patterns in Rocket applications using AI features, such as:

#[get("/chat//messages")]
pub fn get_chat_messages(session_id: String) -> Json<Vec<Message>> {
    // Could expose other users' AI chat sessions
    get_messages_for_session(session_id).unwrap()
}

Runtime detection during development can use Rocket's request guards to log parameter usage patterns. A simple guard that tracks ID parameter access:

pub struct UserIdGuard(pub i32);

impl<'a, 'r> FromRequest<'a, 'r> for UserIdGuard {
    type Error = ();
    
    fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
        let auth_user_id = request.guard::<AuthUser>().unwrap().id;
        let params: Vec<(&'static str, String)> = request.uri().path().split('/')
            .filter(|s| s.starts_with('<') && s.ends_with('>'))
            .map(|s| (s, String::new()))
            .collect();
            
        Outcome::Success(UserIdGuard(auth_user_id))
    }
}

This guard can be extended to log when request parameters don't match the authenticated user, flagging potential BOLA issues.

Rocket-Specific Remediation

Remediating BOLA/IdOR vulnerabilities in Rocket requires implementing proper authorization checks that validate resource ownership before processing requests. The most effective approach leverages Rocket's request guard system for centralized authorization logic.

First, create a reusable ownership guard that validates whether the authenticated user owns the requested resource:

use rocket::request::{FromRequest, Request};
use rocket::outcome::Outcome;
use rocket::http::Status;

pub struct ResourceOwnerGuard<'a> {
    pub resource_user_id: i32,
    pub auth_user: &'a AuthUser,
}

impl<'a, 'r> FromRequest<'a, 'r> for ResourceOwnerGuard<'a> {
    type Error = ();
    
    fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        let auth_user = request.guard::<AuthUser>().unwrap();
        let resource_user_id: i32 = request.get_query_value("id").unwrap_or_default();
        
        if auth_user.id == resource_user_id {
            Outcome::Success(ResourceOwnerGuard { resource_user_id, auth_user })
        } else {
            Outcome::Failure((Status::Forbidden, ()))
        }
    }
}

This guard can be applied to any route that accesses user-specific resources:

#[get("/users//profile")]
pub fn get_user_profile(
    _guard: ResourceOwnerGuard,
    id: i32
) -> Json<UserProfile> {
    // Only accessible if id matches authenticated user
    get_profile_by_id(id).unwrap()
}

For database operations, use Rocket's request guard system to inject validated ownership checks:

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub user_id: i32,
    pub content: String,
}

pub struct OwnedPostGuard(pub Post);

impl<'a, 'r> FromRequest<'a, 'r> for OwnedPostGuard {
    type Error = ();
    
    fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        let auth_user = request.guard::<AuthUser>().unwrap();
        let post_id: i32 = request.get_query_value("post_id").unwrap_or_default();
        
        let post = match get_post_by_id(post_id) {
            Some(p) if p.user_id == auth_user.id => p,
            _ => return Outcome::Failure((Status::NotFound, ())),
        };
        
        Outcome::Success(OwnedPostGuard(post))
    }
}

#[get("/posts/")]
pub fn get_post(guard: OwnedPostGuard) -> Json<Post> {
    Json(guard.0)
}

This pattern ensures that database queries only return resources owned by the authenticated user, preventing unauthorized access.

For JSON request bodies that might contain ID fields, implement validation middleware:

#[derive(Deserialize)]
pub struct UpdateProfileRequest {
    user_id: i32,
    email: String,
}

pub fn validate_request_ownership(req: &UpdateProfileRequest, auth_user: &AuthUser) -> Result<(), &'static str> {
    if req.user_id != auth_user.id {
        return Err("Resource ownership mismatch");
    }
    Ok(())
}

#[put("/update-profile")]
pub fn update_profile(
    auth_user: AuthUser,
    req: Json<UpdateProfileRequest>
) -> Result<Json<UserProfile>> {
    validate_request_ownership(&req.0, &auth_user).unwrap();
    let updated = update_user_profile(auth_user.id, req.email.clone()).unwrap();
    Ok(Json(updated))
}

This validation prevents clients from modifying the user_id field to target other accounts.

For Rocket applications using Diesel or other ORMs, create reusable query functions that include ownership validation:

pub fn get_user_posts(db: &PgConnection, user_id: i32, auth_user_id: i32) -> Result<Vec<Post>> {
    if user_id != auth_user_id {
        return Err("Unauthorized access");
    }
    
    use schema::posts::dsl::*;
    posts.filter(user_id.eq(auth_user_id)).load(db)
}

#[get("/users//posts")]
pub fn get_posts(
    user_id: i32,
    auth_user: AuthUser,
    db: DbConn
) -> Result<Json<Vec<Post>>> {
    let posts = get_user_posts(&db.0, user_id, auth_user.id)?;
    Ok(Json(posts))
}

This pattern centralizes authorization logic in database access functions, making it harder to accidentally introduce BOLA vulnerabilities.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

How does middleBrick detect BOLA vulnerabilities in Rocket applications?
middleBrick performs black-box scanning of Rocket endpoints by analyzing the application's route structure and authentication state. The scanner manipulates ID parameters in authenticated requests to detect unauthorized resource access. For Rocket specifically, it examines dynamic route parameters like and tests whether authenticated users can access resources belonging to other users by changing parameter values. The scanner also analyzes OpenAPI specs generated from Rocket's route table to identify potential BOLA patterns before active testing.
Can Rocket's type system prevent BOLA vulnerabilities?
Rocket's type system alone cannot prevent BOLA vulnerabilities. While Rocket provides type-safe parameter extraction and request guards, it doesn't enforce authorization logic. The framework will happily compile and run code that accesses any resource by ID without checking ownership. BOLA prevention requires explicit authorization checks using Rocket's request guard system or middleware to validate that the authenticated user owns the requested resource before processing the request.