mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Rust: Add integral type barrier for Regex injection.
This commit is contained in:
@@ -24,3 +24,19 @@ class NumericTypeBarrier extends DataFlow::Node {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node whose type is an integral (integer) or boolean type, which may be an
|
||||
* appropriate taint flow barrier for some queries.
|
||||
*/
|
||||
class IntegralOrBooleanTypeBarrier extends DataFlow::Node {
|
||||
IntegralOrBooleanTypeBarrier() {
|
||||
exists(TypeInference::Type t |
|
||||
t = TypeInference::inferType(this.asExpr().getExpr()) and
|
||||
(
|
||||
t.(StructType).getStruct() instanceof IntegralType or
|
||||
t.(StructType).getStruct() instanceof Bool
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.FlowSink
|
||||
private import codeql.rust.Concepts
|
||||
private import codeql.rust.security.Barriers as Barriers
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting regular expression
|
||||
@@ -87,4 +88,13 @@ module RegexInjection {
|
||||
.getText() = "escape"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for regular expression injection vulnerabilities for nodes whose
|
||||
* type is an integral or boolean type, which is unlikely to expose any vulnerability.
|
||||
*
|
||||
* We don't include floating point types in this barrier, as `.` is a special character
|
||||
* in regular expressions.
|
||||
*/
|
||||
private class IntegralOrBooleanTypeBarrier extends Barrier instanceof Barriers::IntegralOrBooleanTypeBarrier { }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#select
|
||||
| main.rs:6:25:6:30 | ®ex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | ®ex | This regular expression is constructed from a $@. | main.rs:4:20:4:32 | ...::var | user-provided value |
|
||||
| main.rs:21:25:21:30 | ®ex | main.rs:19:23:19:35 | ...::var | main.rs:21:25:21:30 | ®ex | This regular expression is constructed from a $@. | main.rs:19:23:19:35 | ...::var | user-provided value |
|
||||
edges
|
||||
| main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | |
|
||||
| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:1 |
|
||||
@@ -9,28 +8,14 @@ edges
|
||||
| main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | |
|
||||
| main.rs:5:25:5:44 | ...::format(...) | main.rs:5:25:5:44 | { ... } | provenance | |
|
||||
| main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | |
|
||||
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:4 |
|
||||
| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:5 |
|
||||
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:3 |
|
||||
| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:4 |
|
||||
| main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | ®ex | provenance | |
|
||||
| main.rs:19:9:19:19 | user_number | main.rs:20:25:20:47 | MacroExpr | provenance | |
|
||||
| main.rs:19:23:19:35 | ...::var | main.rs:19:23:19:43 | ...::var(...) [Ok] | provenance | Src:MaD:1 |
|
||||
| main.rs:19:23:19:43 | ...::var(...) [Ok] | main.rs:19:23:19:70 | ... .unwrap_or(...) | provenance | MaD:2 |
|
||||
| main.rs:19:23:19:70 | ... .unwrap_or(...) | main.rs:19:23:19:85 | ... .parse() [Ok] | provenance | MaD:3 |
|
||||
| main.rs:19:23:19:70 | ... .unwrap_or(...) | main.rs:19:23:19:85 | ... .parse() [Ok] | provenance | MaD:3 |
|
||||
| main.rs:19:23:19:85 | ... .parse() [Ok] | main.rs:19:23:19:98 | ... .unwrap_or(...) | provenance | MaD:2 |
|
||||
| main.rs:19:23:19:98 | ... .unwrap_or(...) | main.rs:19:9:19:19 | user_number | provenance | |
|
||||
| main.rs:20:9:20:13 | regex | main.rs:21:26:21:30 | regex | provenance | |
|
||||
| main.rs:20:25:20:47 | ...::format(...) | main.rs:20:25:20:47 | { ... } | provenance | |
|
||||
| main.rs:20:25:20:47 | ...::must_use(...) | main.rs:20:9:20:13 | regex | provenance | |
|
||||
| main.rs:20:25:20:47 | MacroExpr | main.rs:20:25:20:47 | ...::format(...) | provenance | MaD:4 |
|
||||
| main.rs:20:25:20:47 | { ... } | main.rs:20:25:20:47 | ...::must_use(...) | provenance | MaD:5 |
|
||||
| main.rs:21:26:21:30 | regex | main.rs:21:25:21:30 | ®ex | provenance | |
|
||||
models
|
||||
| 1 | Source: std::env::var; ReturnValue.Field[core::result::Result::Ok(0)]; environment |
|
||||
| 2 | Summary: <core::result::Result>::unwrap_or; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
|
||||
| 3 | Summary: <core::str>::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint |
|
||||
| 4 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
|
||||
| 5 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
|
||||
| 3 | Summary: alloc::fmt::format; Argument[0]; ReturnValue; taint |
|
||||
| 4 | Summary: core::hint::must_use; Argument[0]; ReturnValue; value |
|
||||
nodes
|
||||
| main.rs:4:9:4:16 | username | semmle.label | username |
|
||||
| main.rs:4:20:4:32 | ...::var | semmle.label | ...::var |
|
||||
@@ -43,17 +28,4 @@ nodes
|
||||
| main.rs:5:25:5:44 | { ... } | semmle.label | { ... } |
|
||||
| main.rs:6:25:6:30 | ®ex | semmle.label | ®ex |
|
||||
| main.rs:6:26:6:30 | regex | semmle.label | regex |
|
||||
| main.rs:19:9:19:19 | user_number | semmle.label | user_number |
|
||||
| main.rs:19:23:19:35 | ...::var | semmle.label | ...::var |
|
||||
| main.rs:19:23:19:43 | ...::var(...) [Ok] | semmle.label | ...::var(...) [Ok] |
|
||||
| main.rs:19:23:19:70 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
|
||||
| main.rs:19:23:19:85 | ... .parse() [Ok] | semmle.label | ... .parse() [Ok] |
|
||||
| main.rs:19:23:19:98 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
|
||||
| main.rs:20:9:20:13 | regex | semmle.label | regex |
|
||||
| main.rs:20:25:20:47 | ...::format(...) | semmle.label | ...::format(...) |
|
||||
| main.rs:20:25:20:47 | ...::must_use(...) | semmle.label | ...::must_use(...) |
|
||||
| main.rs:20:25:20:47 | MacroExpr | semmle.label | MacroExpr |
|
||||
| main.rs:20:25:20:47 | { ... } | semmle.label | { ... } |
|
||||
| main.rs:21:25:21:30 | ®ex | semmle.label | ®ex |
|
||||
| main.rs:21:26:21:30 | regex | semmle.label | regex |
|
||||
subpaths
|
||||
|
||||
@@ -16,9 +16,9 @@ fn simple_good_escaped(hay: &str) -> Option<bool> {
|
||||
}
|
||||
|
||||
fn simple_good_numeric(hay: &str) -> Option<bool> {
|
||||
let user_number = std::env::var("USER").unwrap_or("0".to_string()).parse::<u64>().unwrap_or(0); // $ Source=env
|
||||
let user_number = std::env::var("USER").unwrap_or("0".to_string()).parse::<u64>().unwrap_or(0);
|
||||
let regex = format!("foo{}bar", user_number);
|
||||
let re = Regex::new(®ex).unwrap(); // $ SPURIOUS: Alert[rust/regex-injection]=env
|
||||
let re = Regex::new(®ex).unwrap();
|
||||
Some(re.is_match(hay))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user