api: re-validate intercept URL rewrites against the SSRF gate
A Continue resolution that rewrites the request URL applied the new URL after validate_fetch_url had already run on the original, so a rewrite could reach a private or internal address the original request was blocked from. Run the overridden URL back through validate_fetch_url, matching how redirects are re-validated, and return a blocked response if it fails. Also fix a doc comment that ended up attached to the new fetch_response helper instead of stealth_fetch_all.
This commit is contained in:
1 parent
c19a21c142
commit
bd39512ffb
1 file changed
+29
-7
@@ -711,7 +711,26 @@ async fn op_fetch_url(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply interception overrides (shadow the params for the rest of the op).
|
// Apply interception overrides (shadow the params for the rest of the op).
|
||||||
let url = override_url.unwrap_or(url);
|
// A Continue rewrite of the URL must pass the same SSRF / private-network
|
||||||
|
// gate as the original request (checked above) and as redirects (checked
|
||||||
|
// below). Without this re-validation a rewrite to an internal address would
|
||||||
|
// bypass validate_fetch_url entirely.
|
||||||
|
let url = if let Some(new_url) = override_url {
|
||||||
|
if let Ok(parsed) = url::Url::parse(&new_url) {
|
||||||
|
if let Err(reason) = validate_fetch_url(&parsed) {
|
||||||
|
return Ok(serde_json::json!({
|
||||||
|
"status": 0,
|
||||||
|
"body": "",
|
||||||
|
"url": new_url,
|
||||||
|
"blocked": true,
|
||||||
|
"error": format!("Intercept rewrite to forbidden URL blocked: {}", reason),
|
||||||
|
}).to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_url
|
||||||
|
} else {
|
||||||
|
url
|
||||||
|
};
|
||||||
let method = override_method.unwrap_or(method);
|
let method = override_method.unwrap_or(method);
|
||||||
let body = override_body.unwrap_or(body);
|
let body = override_body.unwrap_or(body);
|
||||||
|
|
||||||
@@ -1040,12 +1059,9 @@ async fn op_fetch_url(
|
|||||||
.to_string())
|
.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stealth-mode scripted fetch()/XHR: mirrors op_fetch_url's redirect, SSRF,
|
/// Assemble a `Response` for the on_response interception callbacks from the
|
||||||
/// and CORS semantics but sends every hop through the wreq stealth client so
|
/// parts op_fetch_url already holds. Navigation gets a Response straight from
|
||||||
/// the request carries the Chrome TLS fingerprint and client hints. Cookie
|
/// the http client, but the JS fetch path builds the pieces itself.
|
||||||
/// handling lives inside StealthHttpClient::send_single, which shares the
|
|
||||||
/// context jar. Response bodies are not mirrored into the CDP
|
|
||||||
/// Network.getResponseBody buffer here; that is a follow-up for stealth fetches.
|
|
||||||
fn fetch_response(url: &str, status: u16, headers: HashMap<String, String>, body: Vec<u8>) -> Response {
|
fn fetch_response(url: &str, status: u16, headers: HashMap<String, String>, body: Vec<u8>) -> Response {
|
||||||
Response {
|
Response {
|
||||||
url: url::Url::parse(url).unwrap_or_else(|_| url::Url::parse("http://0.0.0.0/").unwrap()),
|
url: url::Url::parse(url).unwrap_or_else(|_| url::Url::parse("http://0.0.0.0/").unwrap()),
|
||||||
@@ -1056,6 +1072,12 @@ fn fetch_response(url: &str, status: u16, headers: HashMap<String, String>, body
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stealth-mode scripted fetch()/XHR: mirrors op_fetch_url's redirect, SSRF,
|
||||||
|
/// and CORS semantics but sends every hop through the wreq stealth client so
|
||||||
|
/// the request carries the Chrome TLS fingerprint and client hints. Cookie
|
||||||
|
/// handling lives inside StealthHttpClient::send_single, which shares the
|
||||||
|
/// context jar. Response bodies are not mirrored into the CDP
|
||||||
|
/// Network.getResponseBody buffer here; that is a follow-up for stealth fetches.
|
||||||
#[cfg(feature = "stealth")]
|
#[cfg(feature = "stealth")]
|
||||||
async fn stealth_fetch_all(
|
async fn stealth_fetch_all(
|
||||||
stealth: Arc<StealthHttpClient>,
|
stealth: Arc<StealthHttpClient>,
|
||||||
|
|||||||
Reference in new issue
Block a user