Rust: Add request forgery query

This commit is contained in:
Simon Friis Vindum
2025-09-08 13:08:05 +02:00
parent 63a2c9da76
commit e1047dc40b
4 changed files with 200 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
/**
* Provides classes and predicates for reasoning about request forgery
* vulnerabilities.
*/
import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.dataflow.FlowSource
private import codeql.rust.Concepts
private import codeql.rust.security.CleartextTransmissionExtensions
/**
* Provides default sources, sinks and barriers for detecting request forgery
* vulnerabilities, as well as extension points for adding your own.
*/
module RequestForgery {
/**
* A data flow source for request forgery vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for request forgery vulnerabilities.
*/
abstract class Sink extends QuerySink::Range {
/**
* Gets the name of a part of the request that may be tainted by this sink,
* such as the URL or the host.
*/
override string getSinkType() { result = "RequestForgery" }
}
/**
* A barrier for request forgery vulnerabilities.
*/
abstract class Barrier extends DataFlow::Node { }
/**
* An active threat-model source, considered as a flow source.
*/
private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { }
// TODO: Do this in a cleaner way
// private class ClearTextTransmissionSink extends Sink instanceof CleartextTransmission::Sink { }
/**
* A sink for request forgery from model data.
*/
private class ModelsAsDataSink extends Sink {
ModelsAsDataSink() { sinkNode(this, "request-url") }
}
}

View File

@@ -0,0 +1,41 @@
/**
* @name Server-side request forgery
* @description Making a network request with user-controlled data in the URL allows for request forgery attacks.
* @kind path-problem
* @problem.severity error
* @security-severity 9.1
* @precision high
* @id rust/request-forgery
* @tags security
* external/cwe/cwe-918
*/
private import rust
private import codeql.rust.dataflow.TaintTracking
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.Concepts
private import codeql.rust.security.CleartextTransmissionExtensions
private import codeql.rust.security.RequestForgeryExtensions
/**
* A taint-tracking configuration for detecting request forgery vulnerabilities.
*/
module RequestForgeryConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RequestForgery::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgery::Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof RequestForgery::Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
}
module RequestForgeryFlow = TaintTracking::Global<RequestForgeryConfig>;
import RequestForgeryFlow::PathGraph
from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink
where RequestForgeryFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "The $@ of this request depends on a $@.", sink, "URL",
source.getNode(), "user-provided value"

View File

@@ -0,0 +1,105 @@
#select
| request_forgery_tests.rs:8:24:8:35 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:8:24:8:35 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:8:24:8:35 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:8:24:8:35 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:8:24:8:35 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:8:24:8:35 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:17:25:17:36 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:17:25:17:36 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:17:25:17:36 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:21:25:21:36 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:21:25:21:36 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:21:25:21:36 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:25:25:25:36 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:25:25:25:36 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:25:25:25:36 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:31:29:31:40 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:31:29:31:40 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:31:29:31:40 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:31:29:31:40 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:31:29:31:40 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:31:29:31:40 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:37:37:37:48 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:37:37:37:48 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:37:37:37:48 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
| request_forgery_tests.rs:37:37:37:48 | ...::get | request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:37:37:37:48 | ...::get | The $@ of this request depends on a $@. | request_forgery_tests.rs:37:37:37:48 | ...::get | URL | request_forgery_tests.rs:5:29:5:36 | user_url | user-provided value |
edges
| request_forgery_tests.rs:4:5:4:14 | res | request_forgery_tests.rs:16:27:16:49 | { ... } | provenance | |
| request_forgery_tests.rs:4:5:4:14 | res | request_forgery_tests.rs:20:27:20:57 | { ... } | provenance | |
| request_forgery_tests.rs:4:5:4:14 | res | request_forgery_tests.rs:24:27:24:70 | { ... } | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:8:38:8:45 | user_url | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:8:38:8:45 | user_url | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:16:27:16:49 | MacroExpr | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:20:27:20:57 | MacroExpr | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:24:27:24:70 | MacroExpr | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:31:43:31:50 | user_url | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:31:43:31:50 | user_url | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:37:51:37:58 | user_url | provenance | |
| request_forgery_tests.rs:5:29:5:36 | user_url | request_forgery_tests.rs:37:51:37:58 | user_url | provenance | |
| request_forgery_tests.rs:8:37:8:45 | &user_url [&ref] | request_forgery_tests.rs:8:24:8:35 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:8:37:8:45 | &user_url [&ref] | request_forgery_tests.rs:8:24:8:35 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:8:38:8:45 | user_url | request_forgery_tests.rs:8:37:8:45 | &user_url [&ref] | provenance | |
| request_forgery_tests.rs:8:38:8:45 | user_url | request_forgery_tests.rs:8:37:8:45 | &user_url [&ref] | provenance | |
| request_forgery_tests.rs:16:13:16:15 | url | request_forgery_tests.rs:17:39:17:41 | url | provenance | |
| request_forgery_tests.rs:16:27:16:49 | ...::format(...) | request_forgery_tests.rs:4:5:4:14 | res | provenance | |
| request_forgery_tests.rs:16:27:16:49 | ...::must_use(...) | request_forgery_tests.rs:16:13:16:15 | url | provenance | |
| request_forgery_tests.rs:16:27:16:49 | MacroExpr | request_forgery_tests.rs:16:27:16:49 | ...::format(...) | provenance | MaD:291 |
| request_forgery_tests.rs:16:27:16:49 | { ... } | request_forgery_tests.rs:16:27:16:49 | ...::must_use(...) | provenance | MaD:10629 |
| request_forgery_tests.rs:17:38:17:41 | &url [&ref] | request_forgery_tests.rs:17:25:17:36 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:17:39:17:41 | url | request_forgery_tests.rs:17:38:17:41 | &url [&ref] | provenance | |
| request_forgery_tests.rs:20:13:20:15 | url | request_forgery_tests.rs:21:39:21:41 | url | provenance | |
| request_forgery_tests.rs:20:27:20:57 | ...::format(...) | request_forgery_tests.rs:4:5:4:14 | res | provenance | |
| request_forgery_tests.rs:20:27:20:57 | ...::must_use(...) | request_forgery_tests.rs:20:13:20:15 | url | provenance | |
| request_forgery_tests.rs:20:27:20:57 | MacroExpr | request_forgery_tests.rs:20:27:20:57 | ...::format(...) | provenance | MaD:291 |
| request_forgery_tests.rs:20:27:20:57 | { ... } | request_forgery_tests.rs:20:27:20:57 | ...::must_use(...) | provenance | MaD:10629 |
| request_forgery_tests.rs:21:38:21:41 | &url [&ref] | request_forgery_tests.rs:21:25:21:36 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:21:39:21:41 | url | request_forgery_tests.rs:21:38:21:41 | &url [&ref] | provenance | |
| request_forgery_tests.rs:24:13:24:15 | url | request_forgery_tests.rs:25:39:25:41 | url | provenance | |
| request_forgery_tests.rs:24:27:24:70 | ...::format(...) | request_forgery_tests.rs:4:5:4:14 | res | provenance | |
| request_forgery_tests.rs:24:27:24:70 | ...::must_use(...) | request_forgery_tests.rs:24:13:24:15 | url | provenance | |
| request_forgery_tests.rs:24:27:24:70 | MacroExpr | request_forgery_tests.rs:24:27:24:70 | ...::format(...) | provenance | MaD:291 |
| request_forgery_tests.rs:24:27:24:70 | { ... } | request_forgery_tests.rs:24:27:24:70 | ...::must_use(...) | provenance | MaD:10629 |
| request_forgery_tests.rs:25:38:25:41 | &url [&ref] | request_forgery_tests.rs:25:25:25:36 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:25:39:25:41 | url | request_forgery_tests.rs:25:38:25:41 | &url [&ref] | provenance | |
| request_forgery_tests.rs:31:42:31:50 | &user_url [&ref] | request_forgery_tests.rs:31:29:31:40 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:31:42:31:50 | &user_url [&ref] | request_forgery_tests.rs:31:29:31:40 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:31:43:31:50 | user_url | request_forgery_tests.rs:31:42:31:50 | &user_url [&ref] | provenance | |
| request_forgery_tests.rs:31:43:31:50 | user_url | request_forgery_tests.rs:31:42:31:50 | &user_url [&ref] | provenance | |
| request_forgery_tests.rs:37:50:37:58 | &user_url [&ref] | request_forgery_tests.rs:37:37:37:48 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:37:50:37:58 | &user_url [&ref] | request_forgery_tests.rs:37:37:37:48 | ...::get | provenance | MaD:3680 Sink:MaD:3680 |
| request_forgery_tests.rs:37:51:37:58 | user_url | request_forgery_tests.rs:37:50:37:58 | &user_url [&ref] | provenance | |
| request_forgery_tests.rs:37:51:37:58 | user_url | request_forgery_tests.rs:37:50:37:58 | &user_url [&ref] | provenance | |
nodes
| request_forgery_tests.rs:4:5:4:14 | res | semmle.label | res |
| request_forgery_tests.rs:4:5:4:14 | res | semmle.label | res |
| request_forgery_tests.rs:4:5:4:14 | res | semmle.label | res |
| request_forgery_tests.rs:5:29:5:36 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:5:29:5:36 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:8:24:8:35 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:8:24:8:35 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:8:37:8:45 | &user_url [&ref] | semmle.label | &user_url [&ref] |
| request_forgery_tests.rs:8:37:8:45 | &user_url [&ref] | semmle.label | &user_url [&ref] |
| request_forgery_tests.rs:8:38:8:45 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:8:38:8:45 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:16:13:16:15 | url | semmle.label | url |
| request_forgery_tests.rs:16:27:16:49 | ...::format(...) | semmle.label | ...::format(...) |
| request_forgery_tests.rs:16:27:16:49 | ...::must_use(...) | semmle.label | ...::must_use(...) |
| request_forgery_tests.rs:16:27:16:49 | MacroExpr | semmle.label | MacroExpr |
| request_forgery_tests.rs:16:27:16:49 | { ... } | semmle.label | { ... } |
| request_forgery_tests.rs:17:25:17:36 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:17:38:17:41 | &url [&ref] | semmle.label | &url [&ref] |
| request_forgery_tests.rs:17:39:17:41 | url | semmle.label | url |
| request_forgery_tests.rs:20:13:20:15 | url | semmle.label | url |
| request_forgery_tests.rs:20:27:20:57 | ...::format(...) | semmle.label | ...::format(...) |
| request_forgery_tests.rs:20:27:20:57 | ...::must_use(...) | semmle.label | ...::must_use(...) |
| request_forgery_tests.rs:20:27:20:57 | MacroExpr | semmle.label | MacroExpr |
| request_forgery_tests.rs:20:27:20:57 | { ... } | semmle.label | { ... } |
| request_forgery_tests.rs:21:25:21:36 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:21:38:21:41 | &url [&ref] | semmle.label | &url [&ref] |
| request_forgery_tests.rs:21:39:21:41 | url | semmle.label | url |
| request_forgery_tests.rs:24:13:24:15 | url | semmle.label | url |
| request_forgery_tests.rs:24:27:24:70 | ...::format(...) | semmle.label | ...::format(...) |
| request_forgery_tests.rs:24:27:24:70 | ...::must_use(...) | semmle.label | ...::must_use(...) |
| request_forgery_tests.rs:24:27:24:70 | MacroExpr | semmle.label | MacroExpr |
| request_forgery_tests.rs:24:27:24:70 | { ... } | semmle.label | { ... } |
| request_forgery_tests.rs:25:25:25:36 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:25:38:25:41 | &url [&ref] | semmle.label | &url [&ref] |
| request_forgery_tests.rs:25:39:25:41 | url | semmle.label | url |
| request_forgery_tests.rs:31:29:31:40 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:31:29:31:40 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:31:42:31:50 | &user_url [&ref] | semmle.label | &user_url [&ref] |
| request_forgery_tests.rs:31:42:31:50 | &user_url [&ref] | semmle.label | &user_url [&ref] |
| request_forgery_tests.rs:31:43:31:50 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:31:43:31:50 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:37:37:37:48 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:37:37:37:48 | ...::get | semmle.label | ...::get |
| request_forgery_tests.rs:37:50:37:58 | &user_url [&ref] | semmle.label | &user_url [&ref] |
| request_forgery_tests.rs:37:50:37:58 | &user_url [&ref] | semmle.label | &user_url [&ref] |
| request_forgery_tests.rs:37:51:37:58 | user_url | semmle.label | user_url |
| request_forgery_tests.rs:37:51:37:58 | user_url | semmle.label | user_url |
subpaths

View File

@@ -0,0 +1,2 @@
query: queries/security/CWE-918/RequestForgery.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql