Skip to content

Commit 2d0c73a

Browse files
authored
Merge pull request #18501 from geoffw0/rustmetrics
Rust: More metrics for tracking taint.
2 parents 10608bc + e5faf92 commit 2d0c73a

File tree

10 files changed

+193
-11
lines changed

10 files changed

+193
-11
lines changed

rust/ql/integration-tests/hello-project/summary.expected

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
| Macro calls - resolved | 2 |
1515
| Macro calls - total | 2 |
1616
| Macro calls - unresolved | 0 |
17-
| Sensitive data | 0 |
17+
| Taint edges - number of edges | 2 |
18+
| Taint reach - nodes tainted | 0 |
19+
| Taint reach - per million nodes | 0 |
20+
| Taint sinks - cryptographic operations | 0 |
21+
| Taint sinks - query sinks | 0 |
1822
| Taint sources - active | 0 |
19-
| Taint sources - total | 0 |
23+
| Taint sources - disabled | 0 |
24+
| Taint sources - sensitive data | 0 |

rust/ql/integration-tests/hello-workspace/summary.cargo.expected

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
| Macro calls - resolved | 2 |
1515
| Macro calls - total | 2 |
1616
| Macro calls - unresolved | 0 |
17-
| Sensitive data | 0 |
17+
| Taint edges - number of edges | 2 |
18+
| Taint reach - nodes tainted | 0 |
19+
| Taint reach - per million nodes | 0 |
20+
| Taint sinks - cryptographic operations | 0 |
21+
| Taint sinks - query sinks | 0 |
1822
| Taint sources - active | 0 |
19-
| Taint sources - total | 0 |
23+
| Taint sources - disabled | 0 |
24+
| Taint sources - sensitive data | 0 |

rust/ql/integration-tests/hello-workspace/summary.rust-project.expected

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
| Macro calls - resolved | 2 |
1515
| Macro calls - total | 2 |
1616
| Macro calls - unresolved | 0 |
17-
| Sensitive data | 0 |
17+
| Taint edges - number of edges | 2 |
18+
| Taint reach - nodes tainted | 0 |
19+
| Taint reach - per million nodes | 0 |
20+
| Taint sinks - cryptographic operations | 0 |
21+
| Taint sinks - query sinks | 0 |
1822
| Taint sources - active | 0 |
19-
| Taint sources - total | 0 |
23+
| Taint sources - disabled | 0 |
24+
| Taint sources - sensitive data | 0 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @name Cryptographic Operations
3+
* @description List all cryptographic operations found in the database.
4+
* @kind problem
5+
* @problem.severity info
6+
* @id rust/summary/cryptographic-operations
7+
* @tags summary
8+
*/
9+
10+
import rust
11+
import codeql.rust.Concepts
12+
import codeql.rust.security.WeakSensitiveDataHashingExtensions
13+
14+
/**
15+
* Gets the type of cryptographic algorithm `alg`.
16+
*/
17+
string getAlgorithmType(Cryptography::CryptographicAlgorithm alg) {
18+
alg instanceof Cryptography::EncryptionAlgorithm and result = "EncryptionAlgorithm"
19+
or
20+
alg instanceof Cryptography::HashingAlgorithm and result = "HashingAlgorithm"
21+
or
22+
alg instanceof Cryptography::PasswordHashingAlgorithm and result = "PasswordHashingAlgorithm"
23+
}
24+
25+
/**
26+
* Gets a feature of cryptographic algorithm `alg`.
27+
*/
28+
string getAlgorithmFeature(Cryptography::CryptographicAlgorithm alg) {
29+
alg.isWeak() and result = "WEAK"
30+
}
31+
32+
/**
33+
* Gets a description of cryptographic algorithm `alg`.
34+
*/
35+
string describeAlgorithm(Cryptography::CryptographicAlgorithm alg) {
36+
result =
37+
getAlgorithmType(alg) + " " + alg.getName() + " " + concat(getAlgorithmFeature(alg), ", ")
38+
}
39+
40+
/**
41+
* Gets a feature of cryptographic operation `op`.
42+
*/
43+
string getOperationFeature(Cryptography::CryptographicOperation op) {
44+
result = "inputs:" + strictcount(op.getAnInput()).toString() or
45+
result = "blockmodes:" + strictcount(op.getBlockMode()).toString()
46+
}
47+
48+
/**
49+
* Gets a description of cryptographic operation `op`.
50+
*/
51+
string describeOperation(Cryptography::CryptographicOperation op) {
52+
result = describeAlgorithm(op.getAlgorithm()) + " " + concat(getOperationFeature(op), ", ")
53+
or
54+
not exists(op.getAlgorithm()) and
55+
result = "(unknown) " + concat(getOperationFeature(op), ", ")
56+
}
57+
58+
from Cryptography::CryptographicOperation operation
59+
select operation, describeOperation(operation)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @name Query Sink Counts
3+
* @description Lists the number of query sinks of each type found in the database. Query sinks are
4+
* flow sinks that are used as possible locations for query results. Cryptographic
5+
* operations are excluded.
6+
* @kind metric
7+
* @id rust/summary/query-sink-counts
8+
* @tags summary
9+
*/
10+
11+
import rust
12+
import codeql.rust.dataflow.DataFlow
13+
import Stats
14+
15+
from string kind, int num
16+
where num = strictcount(DataFlow::Node n | getAQuerySinkKind(n) = kind)
17+
select kind, num
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @name Query Sinks
3+
* @description Lists query sinks that are found in the database. Query sinks are flow sinks that
4+
* are used as possible locations for query results. Cryptographic operations are
5+
* excluded (see `rust/summary/cryptographic-operations` instead).
6+
* @kind problem
7+
* @problem.severity info
8+
* @id rust/summary/query-sinks
9+
* @tags summary
10+
*/
11+
12+
import rust
13+
import codeql.rust.dataflow.DataFlow
14+
import Stats
15+
16+
from DataFlow::Node n
17+
select n, "Sink for " + strictconcat(getAQuerySinkKind(n), ", ") + "."

rust/ql/src/queries/summary/Stats.qll

+24
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
*/
44

55
import rust
6+
private import codeql.rust.dataflow.DataFlow
67
private import codeql.rust.dataflow.internal.DataFlowImpl
78
private import codeql.rust.dataflow.internal.TaintTrackingImpl
89
private import codeql.rust.AstConsistency as AstConsistency
910
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
1011
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
12+
private import codeql.rust.security.SqlInjectionExtensions
1113

1214
/**
1315
* Gets a count of the total number of lines of code in the database.
@@ -41,3 +43,25 @@ int getTotalCfgInconsistencies() {
4143
int getTotalDataFlowInconsistencies() {
4244
result = sum(string type | | DataFlowConsistency::getInconsistencyCounts(type))
4345
}
46+
47+
/**
48+
* Gets the total number of taint edges in the database.
49+
*/
50+
int getTaintEdgesCount() {
51+
result =
52+
count(DataFlow::Node a, DataFlow::Node b |
53+
RustTaintTracking::defaultAdditionalTaintStep(a, b, _)
54+
)
55+
}
56+
57+
/**
58+
* Gets a kind of query for which `n` is a sink (if any).
59+
*/
60+
string getAQuerySinkKind(DataFlow::Node n) {
61+
(n instanceof SqlInjection::Sink and result = "SqlInjection")
62+
}
63+
64+
/**
65+
* Gets a count of the total number of query sinks in the database.
66+
*/
67+
int getQuerySinksCount() { result = count(DataFlow::Node n | exists(getAQuerySinkKind(n))) }

rust/ql/src/queries/summary/SummaryStats.ql

+17-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import rust
1010
import codeql.rust.Concepts
1111
import codeql.rust.security.SensitiveData
12+
import codeql.rust.security.WeakSensitiveDataHashingExtensions
1213
import codeql.rust.Diagnostics
1314
import Stats
15+
import TaintReach
1416

1517
from string key, int value
1618
where
@@ -54,9 +56,21 @@ where
5456
or
5557
key = "Macro calls - unresolved" and value = count(MacroCall mc | not mc.hasExpanded())
5658
or
57-
key = "Taint sources - total" and value = count(ThreatModelSource s)
58-
or
5959
key = "Taint sources - active" and value = count(ActiveThreatModelSource s)
6060
or
61-
key = "Sensitive data" and value = count(SensitiveData d)
61+
key = "Taint sources - disabled" and
62+
value = count(ThreatModelSource s | not s instanceof ActiveThreatModelSource)
63+
or
64+
key = "Taint sources - sensitive data" and value = count(SensitiveData d)
65+
or
66+
key = "Taint edges - number of edges" and value = getTaintEdgesCount()
67+
or
68+
key = "Taint reach - nodes tainted" and value = getTaintedNodesCount()
69+
or
70+
key = "Taint reach - per million nodes" and value = getTaintReach().floor()
71+
or
72+
key = "Taint sinks - query sinks" and value = getQuerySinksCount()
73+
or
74+
key = "Taint sinks - cryptographic operations" and
75+
value = count(Cryptography::CryptographicOperation o)
6276
select key, value order by key
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Taint reach computation. Taint reach is the proportion of all dataflow nodes that can be reached
3+
* via taint flow from any active thread model source. It's usually expressed per million nodes.
4+
*/
5+
6+
import rust
7+
private import codeql.rust.Concepts
8+
private import codeql.rust.dataflow.DataFlow
9+
private import codeql.rust.dataflow.TaintTracking
10+
11+
/**
12+
* A taint configuration for taint reach (flow to any node from any modeled source).
13+
*/
14+
private module TaintReachConfig implements DataFlow::ConfigSig {
15+
predicate isSource(DataFlow::Node node) { node instanceof ActiveThreatModelSource }
16+
17+
predicate isSink(DataFlow::Node node) { any() }
18+
}
19+
20+
private module TaintReachFlow = TaintTracking::Global<TaintReachConfig>;
21+
22+
/**
23+
* Gets the total number of data flow nodes that taint reaches (from any source).
24+
*/
25+
int getTaintedNodesCount() { result = count(DataFlow::Node n | TaintReachFlow::flowTo(n)) }
26+
27+
/**
28+
* Gets the proportion of data flow nodes that taint reaches (from any source),
29+
* expressed as a count per million nodes.
30+
*/
31+
float getTaintReach() { result = (getTaintedNodesCount() * 1000000.0) / count(DataFlow::Node n) }

rust/ql/test/query-tests/diagnostics/SummaryStats.expected

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
| Macro calls - resolved | 8 |
1515
| Macro calls - total | 9 |
1616
| Macro calls - unresolved | 1 |
17-
| Sensitive data | 0 |
17+
| Taint edges - number of edges | 2 |
18+
| Taint reach - nodes tainted | 0 |
19+
| Taint reach - per million nodes | 0 |
20+
| Taint sinks - cryptographic operations | 0 |
21+
| Taint sinks - query sinks | 0 |
1822
| Taint sources - active | 0 |
19-
| Taint sources - total | 0 |
23+
| Taint sources - disabled | 0 |
24+
| Taint sources - sensitive data | 0 |

0 commit comments

Comments
 (0)