Rust: Add request forgery query qhelp

This commit is contained in:
Simon Friis Vindum
2025-09-08 13:08:36 +02:00
parent e1047dc40b
commit 1c922f0f45
2 changed files with 93 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Directly incorporating user input into an HTTP request without validating the
input can facilitate server-side request forgery (SSRF) attacks. In these
attacks, the server may be tricked into making a request to an unintended API
endpoint or resource.
If the server performing the request is connected to an internal network, this
can give an attacker the means to bypass the network boundary and make requests
against internal services.
A forged request may perform an unintended action on behalf of the attacker, or
cause information leak if redirected to an external server or if the request
response is fed back to the user. It may also compromise the server making the
request, if the request response is handled in an unsafe way.
</p>
</overview>
<recommendation>
<p>
To guard against SSRF attacks you should avoid putting user-provided input
directly into a request URL. Instead, maintain a list of authorized URLs on the
server; then choose from that list based on the input provided. Alternatively,
ensure requests constructed from user input are limited to a particular host or
more restrictive URL prefix.
</p>
</recommendation>
<example>
<p>
The following example shows an HTTP request parameter being used directly to
form a new request without validating the input, which facilitates SSRF attacks.
It also shows how to remedy the problem by validating the user input against a
known fixed string.
</p>
<sample src="RequestForgery.rs" />
</example>
<references>
<li>
<a href="https://owasp.org/www-community/attacks/Server_Side_Request_Forgery">OWASP SSRF</a>
</li>
<li>
<a href="https://cwe.mitre.org/data/definitions/918.html">CWE-918: Server-Side Request Forgery (SSRF)</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,39 @@
// BAD: Endpoint handler that makes requests based on user input
async fn vulnerable_endpoint_handler(req: Request) -> Result<Response> {
// This request is vulnerable to SSRF attacks as the user controls the
// entire URL
let response = reqwest::get(&req.user_url).await;
match response {
Ok(resp) => {
let body = resp.text().await.unwrap_or_default();
Ok(Response {
message: "Success".to_string(),
data: body,
})
}
Err(_) => Err("Request failed")
}
}
// GOOD: Validate user input against an allowlist
async fn secure_endpoint_handler(req: Request) -> Result<Response> {
// Allow list of specific, known-safe URLs
let allowed_hosts = ["api.example.com", "trusted-service.com"];
if !allowed_hosts.contains(&req.user_url) {
return Err("Untrusted domain");
}
// This request is safe as the user input has been validated
let response = reqwest::get(&req.user_url).await;
match response {
Ok(resp) => {
let body = resp.text().await.unwrap_or_default();
Ok(Response {
message: "Success".to_string(),
data: body,
})
}
Err(_) => Err("Request failed")
}
}