HIGH cache poisoningrocket

Cache Poisoning in Rocket

How Cache Poisoning Manifests in Rocket

Cache poisoning in Rocket applications typically exploits the framework's response caching mechanisms, which can be configured through Rocket's built-in cache control features or third-party middleware. The most common attack vector involves manipulating cache keys to inject malicious content that gets served to other users.

In Rocket, cache poisoning often occurs through improper handling of Vary headers. When an endpoint fails to properly specify which request headers should influence the cached response, attackers can craft requests with specific headers to poison the cache. For example, a Rocket route that serves user-specific data without properly varying on authentication headers might cache sensitive information and serve it to unauthorized users.

#[get("/user/profile")]
pub fn profile(&user: User) -> Json<UserProfile> {
    // Missing Vary: Authorization header
    // Cache could serve User A's profile to User B
    Json(user.profile.clone())
}

Another Rocket-specific manifestation involves query parameter manipulation. Rocket's default query parameter parsing can lead to cache key collisions when different query parameters produce the same logical response but different cache keys. An attacker might exploit this by crafting URLs that bypass intended access controls.

#[get("/api/data")]
pub fn get_data(
    query: Option<String>, 
    #[header("Authorization")] auth: Option<String>
) -> Json<ApiResponse> {
    // If cache key only considers 'query' but not 'auth',
    // an attacker could poison cache with unauthorized data
    let data = if auth.is_some() {
        get_sensitive_data()
    } else {
        get_public_data()
    };
    Json(data)
}

Header injection attacks are particularly dangerous in Rocket applications that use custom response headers for caching directives. An attacker might manipulate headers to extend cache lifetimes or bypass cache invalidation mechanisms.

Rocket-Specific Detection

Detecting cache poisoning vulnerabilities in Rocket requires examining both the application code and runtime behavior. Start by auditing your Rocket routes for proper cache control implementation. Look for missing Vary headers, inconsistent cache key generation, and improper handling of authentication state in cached responses.

middleBrick's API security scanner can identify Rocket-specific cache poisoning vulnerabilities through its black-box scanning approach. The scanner tests unauthenticated endpoints for cache-related issues by examining response headers, cache control directives, and testing for sensitive data exposure in cached responses.

Key detection patterns include:

  • Missing or incorrect Vary headers on authenticated endpoints
  • Cache control headers that allow public caching of sensitive data
  • Query parameter handling that creates cache key collisions
  • Header manipulation that affects caching behavior
  • Stale cache responses that don't reflect recent authorization changes

middleBrick's scanning engine specifically tests for these Rocket patterns by sending requests with varying authentication states, custom headers, and query parameters to detect inconsistent caching behavior. The scanner's LLM security module also checks for AI-specific cache poisoning scenarios if your Rocket application uses language model endpoints.

Runtime detection can be implemented using Rocket's request guards and middleware to log cache-related anomalies:

use rocket::request::Request;
use rocket::response::Response;
use rocket::fairing::{Fairing, Info, Kind};

struct CacheAuditFairing;

impl Fairing for CacheAuditFairing {
    fn info(&self) -> Info {
        Info {
            name: "Cache Audit",
            kind: Kind::Response
        }
    }

    fn on_response(&self, request: &Request, response: &mut Response) {
        if let Some(cache_control) = response.headers().get_one("Cache-Control") {
            // Log suspicious cache configurations
            if cache_control.contains("public") && 
               request.headers().get_one("Authorization).is_some() {
                warn!("Public cache on authenticated endpoint");
            }
        }
    }
}

Rocket-Specific Remediation

Remediating cache poisoning in Rocket applications requires a multi-layered approach focusing on proper cache control configuration, secure header handling, and appropriate cache key generation. The foundation is implementing correct Vary headers and cache control directives.

For authenticated endpoints that should never be cached, use Rocket's response builders with explicit cache control:

#[get("/user/sensitive-data")]
pub fn sensitive_data(
    #[header("Authorization")] auth: String
) -> Result<Json<SensitiveData>, Status> {
    // Never cache sensitive data
    let data = get_sensitive_data_for_user(auth);
    let mut response = Json(data).into_response();
    response.set_header(rocket::http::Header::new(
        "Cache-Control", 
        "no-store, no-cache, must-revalidate, private"
    ));
    response.set_header(rocket::http::Header::new(
        "Pragma", 
        "no-cache"
    ));
    response.set_header(rocket::http::Header::new(
        "Vary", 
        "Authorization, Cookie"
    ));
    Ok(response)
}

For endpoints that can be cached but require proper variation, implement explicit Vary headers and cache key generation:

#[get("/api/search")]
pub fn search(
    query: String,
    #[header("Accept-Language")] lang: String,
    #[header("Authorization")] auth: Option<String>
) -> Json<SearchResults> {
    let results = perform_search(query, lang, auth.is_some());
    let mut response = Json(results).into_response();
    
    // Vary on query, language, and auth state
    response.set_header(rocket::http::Header::new(
        "Vary", 
        "Authorization, Accept-Language, Query"
    ));
    
    // Allow caching but only for 5 minutes
    response.set_header(rocket::http::Header::new(
        "Cache-Control", 
        "public, max-age=300, must-revalidate"
    ));
    
    Ok(response)
}

Implement cache key generation that includes all relevant request parameters:

use rocket::request::Request;
use rocket::response::content::Json;

fn generate_cache_key(request: &Request) -> String {
    let mut key = String::new();
    
    // Include path and query
    key.push_str(request.uri().path());
    if let Some(query) = request.uri().query() {
        key.push_str("?");
        key.push_str(query);
    }
    
    // Include authentication state
    if let Some(auth) = request.headers().get_one("Authorization") {
        key.push_str("|auth:");
        key.push_str(&auth[..4]); // partial for key
    }
    
    // Include language and other relevant headers
    if let Some(lang) = request.headers().get_one("Accept-Language") {
        key.push_str("|lang:");
        key.push_str(lang);
    }
    
    key
}

For applications using Rocket with Redis or other external caches, implement proper cache invalidation strategies:

use rocket_contrib::databases::redis::Connection;

#[post("/user/update")]
pub fn update_user(
    user: User,
    #[database("redis_cache")] cache: Connection
) -> Json<User> {
    let updated = update_user_in_db(user);
    
    // Invalidate related cache entries
    let cache_key = format!("user:{}", updated.id);
    cache.del(cache_key).unwrap();
    
    Json(updated)
}

Frequently Asked Questions

How does Rocket's default caching behavior differ from other frameworks?
Rocket doesn't enable caching by default, but it provides flexible cache control through response builders and middleware. Unlike frameworks with opinionated caching layers, Rocket requires explicit configuration of cache headers and vary directives, which can lead to security gaps if developers aren't aware of proper cache control implementation.
Can middleBrick detect cache poisoning in Rocket applications without source code access?
Yes, middleBrick's black-box scanning approach tests Rocket endpoints by sending requests with varying authentication states, headers, and query parameters to detect inconsistent caching behavior. The scanner examines response headers, cache control directives, and tests for sensitive data exposure in cached responses without requiring access to your source code or deployment environment.