HIGH clickjackingrocketbasic auth

Clickjacking in Rocket with Basic Auth

Clickjacking in Rocket with Basic Auth — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side attack that tricks a user into interacting with a hidden or disguised UI element inside an iframe. When Rocket routes are protected only by HTTP Basic Auth and are embedded cross-origin, the combination can expose authentication flows to clickjacking without additional anti-clickjacking controls. Because Basic Auth credentials are sent automatically by the browser when the protected route is loaded in an iframe, an attacker can overlay invisible UI elements on top of the embedded authentication dialog or lure the user to perform actions that are interpreted by the Rocket app as intentional credentials submission.

Consider a Rocket endpoint that does not set X-Frame-Options or Content-Security-Policy (CSP) frame-ancestors, and requires Basic Auth. An attacker can create a page that embeds https://api.example.com/protected inside an invisible or disguised iframe. The browser will show the native Basic Auth dialog (if credentials are not yet cached), and the attacker can position fake buttons or text over the dialog. Even if the dialog is cached, the attacker can trigger authenticated state changes by performing CSRF-like actions within the authenticated session once the user has logged in, because the browser will include the Basic Auth header automatically on subsequent requests initiated from the embedded context.

Basic Auth does not inherently prevent framing; it only ensures that credentials are sent with each request. Therefore, the presence of Basic Auth does not mitigate clickjacking. In Rocket, if routes are not explicitly protected from being embedded, an authenticated session can be abused via UI redressing. This is especially risky when the response includes sensitive information or forms that can be triggered via GET requests, as the browser will send credentials automatically when the iframe loads the protected resource. MiddleBrick’s scans detect missing anti-framing headers and report this as a high-severity finding under Data Exposure and Input Validation checks, highlighting the need for explicit frame-ancestor policies.

Basic Auth-Specific Remediation in Rocket — concrete code fixes

To prevent clickjacking in Rocket when using Basic Auth, you must explicitly control which origins can embed your responses. The recommended approach is to set X-Frame-Options for backward compatibility and a strong Content-Security-Policy frame-ancestors directive. For modern applications, CSP is preferred because it is more flexible and future-proof.

Below is a minimal Rocket example that applies both headers to all responses, denying embedding from any origin except your own frontend domain. This ensures that even if credentials are cached, the page cannot be loaded inside an attacker-controlled iframe.

use rocket::{Build, Rocket, State};
use rocket::response::Response;
use rocket::http::Header;

// Attach security headers to every response
#[rocket::catchall]
fn catchall() -> Response {
    let mut response = Response::build();
    response.insert_header(Header::new("X-Frame-Options", "DENY"));
    response.insert_header(Header::new(
        "Content-Security-Policy",
        "frame-ancestors 'self' https://trusted-frontend.example.com;"
    ));
    response.ok()
}

#[launch]
fn rocket() -> _ {
    rocket::build()
        .register("/", catchers![catchall])
        // Your routes here, protected by Basic Auth
}

If you prefer to apply these headers selectively to specific routes, you can attach fairings or guards that inject headers only for authenticated endpoints. The following example shows how to add the same headers to a single protected route:

use rocket::get;
use rocket::response::Response;
use rocket::http::Header;

#[get("/api/secure")]
fn secure_endpoint() -> Response {
    let mut response = Response::build();
    response.insert_header(Header::new("X-Frame-Options", "SAMEORIGIN"));
    response.insert_header(Header::new(
        "Content-Security-Policy",
        "frame-ancestors 'self'"
    ));
    response.ok()
}

// Combine with Basic Auth guards as needed
#[rocket::main]
async fn main() {
    rocket::build()
        .mount("/", routes![secure_endpoint])
        .launch()
        .await
        .unwrap();
}

Note that Basic Auth credentials are still transmitted with each request; these headers prevent the browser from rendering the protected page in a cross-origin frame, thereby neutralizing the clickjacking vector. MiddleBrick’s scans validate the presence of these headers and flag endpoints that lack frame-ancestor directives or rely on deprecated mitigations.

Frequently Asked Questions

Does Basic Auth alone prevent clickjacking in Rocket?
No. Basic Auth only ensures credentials are sent with requests; it does not prevent a page from being embedded in an iframe. You must explicitly set X-Frame-Options or CSP frame-ancestors to prevent clickjacking.
Should I use X-Frame-Options DENY or SAMEORIGIN with Basic Auth?
Use DENY if your endpoints should never be framed. Use SAMEORIGIN if you need to allow embedding from your own domain. For modern CSP support, prefer frame-ancestors 'self' over X-Frame-Options when both are present.