Skip to content

Commit 9fb00da

Browse files
committed
Rust: Implement the query (with one source, one sink model).
1 parent bd75f01 commit 9fb00da

File tree

5 files changed

+109
-6
lines changed

5 files changed

+109
-6
lines changed

rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ extensions:
88
- ["repo:https://github.com/RustCrypto/traits:digest", "<_ as crate::digest::Digest>::chain_update", "Argument[0]", "hasher-input", "manual"]
99
- ["repo:https://github.com/RustCrypto/traits:digest", "<_ as crate::digest::Digest>::digest", "Argument[0]", "hasher-input", "manual"]
1010
- ["repo:https://github.com/stainless-steel/md5:md5", "crate::compute", "Argument[0]", "hasher-input", "manual"]
11+
- ["repo:https://github.com/RustCrypto/traits:crypto-common", "crate::KeyInit::new_from_slice", "Argument[0]", "credentials-key", "manual"]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Provides classes and predicates for reasoning about hardcoded cryptographic value
3+
* vulnerabilities.
4+
*/
5+
6+
import rust
7+
private import codeql.rust.dataflow.DataFlow
8+
private import codeql.rust.dataflow.internal.DataFlowImpl
9+
private import codeql.rust.security.SensitiveData
10+
11+
/**
12+
* Provides default sources, sinks and barriers for detecting hardcoded cryptographic
13+
* value vulnerabilities, as well as extension points for adding your own.
14+
*/
15+
module HardcodedCryptographicValue {
16+
/**
17+
* A data flow source for hardcoded cryptographic value vulnerabilities.
18+
*/
19+
abstract class Source extends DataFlow::Node { }
20+
21+
/**
22+
* A data flow sink for hardcoded cryptographic value vulnerabilities.
23+
*/
24+
abstract class Sink extends DataFlow::Node {
25+
/**
26+
* Gets the kind of credential this sink is interpreted as,
27+
* for example "password", "key", "iv", "salt".
28+
*/
29+
abstract string getKind();
30+
}
31+
32+
/**
33+
* A barrier for hardcoded cryptographic value vulnerabilities.
34+
*/
35+
abstract class Barrier extends DataFlow::Node { }
36+
37+
/**
38+
* A literal, considered as a flow source.
39+
*/
40+
private class LiteralSource extends Source {
41+
LiteralSource() { this.asExpr().getExpr() instanceof LiteralExpr }
42+
}
43+
44+
/**
45+
* A sink for hardcoded cryptographic value from model data.
46+
*/
47+
private class ModelsAsDataSinks extends Sink {
48+
string kind;
49+
50+
ModelsAsDataSinks() {
51+
kind = ["password", "key", "iv", "salt"] and
52+
sinkNode(this, "credentials-" + kind)
53+
}
54+
55+
override string getKind() { result = kind }
56+
}
57+
}

rust/ql/src/queries/security/CWE-798/HardcodedCryptographicValue.ql

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @name Hard-coded cryptographic value
33
* @description Using hardcoded keys, passwords, salts or initialization
44
* vectors is not secure.
5-
* @kind problem
5+
* @kind path-problem
66
* @problem.severity warning
77
* @security-severity TODO
88
* @precision high
@@ -15,7 +15,36 @@
1515
*/
1616

1717
import rust
18+
import codeql.rust.security.HardcodedCryptographicValueExtensions
19+
import codeql.rust.dataflow.DataFlow
20+
import codeql.rust.dataflow.TaintTracking
21+
import codeql.rust.dataflow.internal.DataFlowImpl
1822

19-
from Locatable e
20-
where none()
21-
select e, ""
23+
/**
24+
* A taint-tracking configuration for hardcoded cryptographic value vulnerabilities.
25+
*/
26+
module HardcodedCryptographicValueConfig implements DataFlow::ConfigSig {
27+
import HardcodedCryptographicValue
28+
29+
predicate isSource(DataFlow::Node source) { source instanceof Source }
30+
31+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
32+
33+
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
34+
35+
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
36+
// flow out from reference content at sinks.
37+
isSink(node) and
38+
c.getAReadContent() instanceof ReferenceContent
39+
}
40+
}
41+
42+
module HardcodedCryptographicValueFlow = TaintTracking::Global<HardcodedCryptographicValueConfig>;
43+
44+
import HardcodedCryptographicValueFlow::PathGraph
45+
46+
from
47+
HardcodedCryptographicValueFlow::PathNode source, HardcodedCryptographicValueFlow::PathNode sink
48+
where HardcodedCryptographicValueFlow::flowPath(source, sink)
49+
select source.getNode(), source, sink, "This hard-coded value is used as $@.", sink,
50+
sink.getNode().(HardcodedCryptographicValueConfig::Sink).getKind()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#select
2+
| test_cipher.rs:73:20:73:22 | 0u8 | test_cipher.rs:73:20:73:22 | 0u8 | test_cipher.rs:74:23:74:44 | ...::new_from_slice | This hard-coded value is used as $@. | test_cipher.rs:74:23:74:44 | ...::new_from_slice | key |
3+
edges
4+
| test_cipher.rs:73:9:73:14 | const2 [&ref, element] | test_cipher.rs:74:46:74:51 | const2 [&ref, element] | provenance | |
5+
| test_cipher.rs:73:18:73:26 | &... [&ref, element] | test_cipher.rs:73:9:73:14 | const2 [&ref, element] | provenance | |
6+
| test_cipher.rs:73:19:73:26 | [0u8; 32] [element] | test_cipher.rs:73:18:73:26 | &... [&ref, element] | provenance | |
7+
| test_cipher.rs:73:20:73:22 | 0u8 | test_cipher.rs:73:19:73:26 | [0u8; 32] [element] | provenance | |
8+
| test_cipher.rs:74:46:74:51 | const2 [&ref, element] | test_cipher.rs:74:23:74:44 | ...::new_from_slice | provenance | MaD:54 Sink:MaD:54 Sink:MaD:54 |
9+
nodes
10+
| test_cipher.rs:73:9:73:14 | const2 [&ref, element] | semmle.label | const2 [&ref, element] |
11+
| test_cipher.rs:73:18:73:26 | &... [&ref, element] | semmle.label | &... [&ref, element] |
12+
| test_cipher.rs:73:19:73:26 | [0u8; 32] [element] | semmle.label | [0u8; 32] [element] |
13+
| test_cipher.rs:73:20:73:22 | 0u8 | semmle.label | 0u8 |
14+
| test_cipher.rs:74:23:74:44 | ...::new_from_slice | semmle.label | ...::new_from_slice |
15+
| test_cipher.rs:74:46:74:51 | const2 [&ref, element] | semmle.label | const2 [&ref, element] |
16+
subpaths

rust/ql/test/query-tests/security/CWE-798/test_cipher.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ fn test_block_cipher_aes(
7070
let aes_cipher3 = Aes256::new_from_slice(key256).unwrap();
7171
aes_cipher3.encrypt_block(block128.into());
7272

73-
let const2 = &[0u8;32]; // $ MISSING: Alert[rust/hardcoded-crytographic-value]
74-
let aes_cipher4 = Aes256::new_from_slice(const2).unwrap();
73+
let const2 = &[0u8;32]; // $ Alert[rust/hardcoded-crytographic-value]
74+
let aes_cipher4 = Aes256::new_from_slice(const2).unwrap(); // $ Sink
7575
aes_cipher4.encrypt_block(block128.into());
7676

7777
let aes_cipher5 = cfb_mode::Encryptor::<aes::Aes256>::new(key.into(), iv.into());

0 commit comments

Comments
 (0)