Auth Bypass in Rocket
How Auth Bypass Manifests in Rocket
Auth bypass vulnerabilities in Rocket applications typically emerge through several specific attack vectors. The most common pattern involves improper route protection where authentication guards are either missing or incorrectly configured. In Rocket, this often manifests when developers use the #[get] or #[post] attributes without the #[guard] attribute, leaving sensitive endpoints exposed to unauthenticated access.
A classic example is the missing authentication guard on admin routes. Consider this vulnerable pattern:
#[get("/admin/users")]
fn list_users() -> Json<Vec<User>> {
// Returns all users without authentication
db::get_all_users()
}
// Should be:
#[get("/admin/users")]
#[guard(AdminGuard)]
fn list_users() -> Json<Vec<User>> {
// Now requires admin authentication
db::get_all_users()
}
Another prevalent issue is broken token validation. Rocket applications often use JWT tokens, but developers sometimes implement weak validation logic:
// VULNERABLE: Missing signature verification
fn verify_token(token: &str) -> Result<Claims, Error> {
let token = token.strip_prefix("Bearer ").unwrap_or(token);
let decoded = jwt::decode(token, &DecodingKey::from_secret(secret.as_bytes()), &Validation::new(Algorithm::HS256));
decoded.map_err(|_| Error::InvalidToken)
}
// SECURE: Proper signature verification with algorithm validation
fn verify_token(token: &str) -> Result<Claims, Error> {
let token = token.strip_prefix("Bearer ").unwrap_or(token);
let validation = Validation::new(Algorithm::HS256)
.validate_exp(true)
.validate_nbf(true);
let decoded = jwt::decode(token, &DecodingKey::from_secret(secret.as_bytes()), &validation);
decoded.map_err(|_| Error::InvalidToken)
}
Session fixation attacks also pose a significant risk in Rocket applications. When session IDs are not properly regenerated upon authentication, attackers can hijack user sessions:
// VULNERABLE: Session ID not regenerated
#[post("/login")]
fn login(mut sess: &Session, form: Form<Login>) -> Redirect {
if auth::verify(form.username, form.password) {
sess.insert("user_id", form.username.clone());
Redirect::to("/dashboard")
} else {
Redirect::to("/login")
}
}
// SECURE: Session ID regenerated on login
#[post("/login")]
fn login(mut sess: &Session, form: Form<Login>) -> Redirect {
if auth::verify(form.username, form.password) {
sess.regenerate(); // Critical: prevents session fixation
sess.insert("user_id", form.username.clone());
Redirect::to("/dashboard")
} else {
Redirect::to("/login")
}
}
Parameter pollution is another Rocket-specific vulnerability where multiple authentication parameters can confuse the framework's routing logic. This can lead to unexpected authentication bypass:
// VULNERABLE: Parameter pollution possible
#[get("/api/resource?&")]
fn get_resource(id: String, token: String) -> Json<Resource> {
// If token validation fails, function still executes
if !auth::validate_token(&token) {
return Json(Resource::unauthorized());
}
db::get_resource(id)
}
// SECURE: Early return on failed validation
#[get("/api/resource?&")]
fn get_resource(id: String, token: String) -> Result<Json<Resource>> {
if !auth::validate_token(&token) {
return Err(Error::Unauthorized);
}
Ok(Json(db::get_resource(id)))
}
Rocket-Specific Detection
Detecting auth bypass vulnerabilities in Rocket applications requires a multi-faceted approach. The most effective method is runtime scanning that mimics attacker behavior. middleBrick's black-box scanning approach is particularly effective here because it tests the actual running application without requiring source code access.
middleBrick scans Rocket APIs by sending requests to endpoints and analyzing responses. For auth bypass detection, it specifically tests:
- Unauthenticated access to protected endpoints
- Token validation bypass attempts
- Session fixation scenarios
- Parameter pollution edge cases
- Role-based access control violations
The scanner sends crafted requests to identify authentication weaknesses. For example, it might attempt to access an admin endpoint without credentials, or send malformed tokens to test validation logic. When Rocket returns sensitive data without proper authentication, middleBrick flags this as a critical vulnerability.
middleBrick's LLM/AI security module is particularly relevant for Rocket applications that integrate AI features. It tests for system prompt leakage and prompt injection vulnerabilities that could bypass authentication in AI-powered endpoints. The scanner uses 27 regex patterns to detect ChatML, Llama 2, Mistral, and Alpaca format leaks, then actively probes with five sequential injection attempts.
For development teams using Rocket, middleBrick offers several integration options. The CLI tool allows you to scan your API directly from the terminal:
npx middlebrick scan https://your-rocket-app.com/api
This provides immediate feedback on auth bypass vulnerabilities without modifying your codebase. The GitHub Action integration enables continuous security testing:
steps:
- name: Run middleBrick Scan
uses: middleBrick/middlebrick-action@v1
with:
api_url: https://staging.your-rocket-app.com
fail_threshold: C
middleBrick's OpenAPI/Swagger analysis is especially valuable for Rocket applications since Rocket's code generation creates OpenAPI specs. The scanner cross-references your spec definitions with runtime findings, ensuring that documented authentication requirements match actual implementation.
Key detection capabilities include:
- Testing endpoints listed as protected in OpenAPI specs but accessible without credentials
- Verifying that rate limiting applies to authentication endpoints
- Checking for exposed admin functionality
- Detecting missing or weak JWT validation
- Identifying session management flaws
The scanner provides detailed reports with severity levels, affected endpoints, and specific remediation guidance. For auth bypass issues, middleBrick typically assigns high or critical severity due to the direct impact on data confidentiality.
Rocket-Specific Remediation
Remediating auth bypass vulnerabilities in Rocket requires both code-level fixes and architectural improvements. The foundation is proper authentication guard implementation. Rocket's guard system provides robust protection when used correctly:
use rocket::http::Status;
use rocket::request::{self, FromRequest, Request};
use rocket::Outcome;
struct AuthenticatedUser { user_id: String }
#[rocket::async_trait]
impl<'r> FromRequest<'r> for AuthenticatedUser {
type Error = ();
async fn from_request(request: &'r Request<'_, '_>) -> Outcome<Self, Self::Error> {
let token = request.headers().get_one("Authorization");
match token {
Some(token) => {
match auth::validate_token(token) {
Ok(user_id) => Outcome::Success(AuthenticatedUser { user_id }),
Err(_) => Outcome::Failure((Status::Unauthorized, ())),
}
}
None => Outcome::Failure((Status::Unauthorized, ())),
}
}
}
// Now protect routes:
#[get("/api/protected")]
#[guard(AuthenticatedUser)]
fn protected_resource(_user: AuthenticatedUser) -> Json<Resource> {
Json(Resource::authorized())
}
For role-based access control, create specific guards for different permission levels:
#[rocket::async_trait]
impl<'r> FromRequest<'r> for AdminUser {
type Error = ();
async fn from_request(request: &'r Request<'_, '_>) -> Outcome<Self, Self::Error> {
let user = AuthenticatedUser::from_request(request).await;
match user {
Outcome::Success(user) => {
if auth::is_admin(&user.user_id) {
Outcome::Success(AdminUser { user_id: user.user_id })
} else {
Outcome::Failure((Status::Forbidden, ()))
}
}
Outcome::Failure(_) => Outcome::Failure((Status::Unauthorized, ())),
}
}
}
#[get("/admin/dashboard")]
#[guard(AdminUser)]
fn admin_dashboard(_admin: AdminUser) -> Html<String> {
Html("<h1>Admin Dashboard</h1>".to_string())
}
Session management requires special attention in Rocket applications. Always regenerate session IDs upon authentication and use secure cookie settings:
#[post("/login")]
fn login(mut sess: &Session, form: Form<Login>) -> Redirect {
if auth::verify(form.username, form.password) {
sess.regenerate();
sess.set("user_id", form.username.clone());
sess.set("csrf_token", uuid::Uuid::new_v4().to_string());
// Secure cookie settings
sess.set_cookie_name("rocket_auth_session");
sess.set_cookie_secure(true);
sess.set_cookie_http_only(true);
sess.set_cookie_same_site(rocket::http::SameSite::Lax);
Redirect::to("/dashboard")
} else {
Redirect::to("/login")
}
}
Input validation is critical for preventing parameter pollution attacks. Use Rocket's request guard system to validate parameters before they reach your route handlers:
use rocket::request::FromFormValue;
struct ValidToken(String);
#[rocket::async_trait]
impl FromFormValue<'v> for ValidToken {
type Error = &'static str;
fn from_form_value(form_value: &'v str) -> Result<Self, Self::Error> {
if auth::validate_token(form_value) {
Ok(ValidToken(form_value.to_string()))
} else {
Err("Invalid token")
}
}
}
#[get("/api/resource?&\ ValidToken>]
fn get_resource(id: String, token: ValidToken) -> Json<Resource> {
// Token is guaranteed valid by the guard
Json(db::get_resource(id))
}
For comprehensive protection, implement security headers and CORS policies:
use rocket::fairing::AdHoc;
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(AdHoc::on_response("Security Headers", |request, response| {
response.set_header("X-Content-Type-Options", "nosniff");
response.set_header("X-Frame-Options", "DENY");
response.set_header("X-XSS-Protection", "1; mode=block");
response.set_header("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
}))
.mount("/", routes![...])
}
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |