Skip to content

Commit d258f69

Browse files
authored
Merge pull request github#14329 from geoffw0/sinks
Swift: Update summary queries
2 parents 34b33e1 + 8e9ca7b commit d258f69

File tree

5 files changed

+166
-33
lines changed

5 files changed

+166
-33
lines changed

swift/ql/src/queries/Summary/FlowSources.ql

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@
99
* @tags summary
1010
*/
1111

12+
/*
13+
* Most queries compute data flow from one of the following sources:
14+
* - flow sources (listed by this query, `swift/summary/flow-sources`).
15+
* - sensitive expressions (see `swift/summary/sensitive-expressions`).
16+
* - constant values.
17+
* - custom per-query sources.
18+
*/
19+
1220
import swift
1321
import codeql.swift.dataflow.FlowSources
1422

1523
string sourceClass(FlowSource s) {
16-
s instanceof LocalFlowSource and result = "LocalFlowSource"
24+
s instanceof LocalFlowSource and result = "Local flow source"
1725
or
18-
s instanceof RemoteFlowSource and result = "RemoteFlowSource"
26+
s instanceof RemoteFlowSource and result = "Remote flow source"
1927
}
2028

2129
from FlowSource s
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* @name Query Sinks
3+
* @description List all query sinks found in the database. Query sinks are
4+
* potential results depending on what data flows to them and
5+
* other context.
6+
* @kind problem
7+
* @problem.severity info
8+
* @id swift/summary/query-sinks
9+
* @tags summary
10+
*/
11+
12+
/*
13+
* Most queries compute data flow to one of the following sinks:
14+
* - custom per-query sinks (listed by this query, `swift/summary/query-sinks`).
15+
* - regular expression evaluation (see `swift/summary/regex-evals`).
16+
*/
17+
18+
import swift
19+
import codeql.swift.dataflow.DataFlow
20+
import codeql.swift.security.PathInjectionQuery
21+
import codeql.swift.security.UnsafeWebViewFetchQuery
22+
import codeql.swift.security.SqlInjectionQuery
23+
import codeql.swift.security.UnsafeJsEvalQuery
24+
import codeql.swift.security.UncontrolledFormatStringQuery
25+
import codeql.swift.security.StringLengthConflationQuery
26+
import codeql.swift.security.ConstantPasswordQuery
27+
import codeql.swift.security.CleartextStorageDatabaseQuery
28+
import codeql.swift.security.CleartextTransmissionQuery
29+
import codeql.swift.security.CleartextLoggingQuery
30+
import codeql.swift.security.CleartextStoragePreferencesQuery
31+
import codeql.swift.security.HardcodedEncryptionKeyQuery
32+
import codeql.swift.security.ECBEncryptionQuery
33+
import codeql.swift.security.WeakSensitiveDataHashingQuery
34+
import codeql.swift.security.XXEQuery
35+
import codeql.swift.security.InsecureTLSQuery
36+
import codeql.swift.security.ConstantSaltQuery
37+
import codeql.swift.security.InsufficientHashIterationsQuery
38+
import codeql.swift.security.PredicateInjectionQuery
39+
import codeql.swift.security.StaticInitializationVectorQuery
40+
41+
string queryForSink(DataFlow::Node sink) {
42+
PathInjectionConfig::isSink(sink) and result = "swift/path-injection"
43+
or
44+
UnsafeWebViewFetchConfig::isSink(sink) and result = "swift/unsafe-webview-fetch"
45+
or
46+
SqlInjectionConfig::isSink(sink) and result = "swift/sql-injection"
47+
or
48+
UnsafeJsEvalConfig::isSink(sink) and result = "swift/unsafe-js-eval"
49+
or
50+
TaintedFormatConfig::isSink(sink) and result = "swift/uncontrolled-format-string"
51+
or
52+
StringLengthConflationConfig::isSink(sink) and result = "swift/string-length-conflation"
53+
or
54+
ConstantPasswordConfig::isSink(sink) and result = "swift/constant-password"
55+
or
56+
CleartextStorageDatabaseConfig::isSink(sink) and result = "swift/cleartext-storage-database"
57+
or
58+
CleartextTransmissionConfig::isSink(sink) and result = "swift/cleartext-transmission"
59+
or
60+
CleartextLoggingConfig::isSink(sink) and result = "swift/cleartext-logging"
61+
or
62+
CleartextStoragePreferencesConfig::isSink(sink) and result = "swift/cleartext-storage-preferences"
63+
or
64+
HardcodedKeyConfig::isSink(sink) and result = "swift/hardcoded-key"
65+
or
66+
EcbEncryptionConfig::isSink(sink) and result = "swift/ecb-encryption"
67+
or
68+
WeakHashingConfig::isSink(sink) and result = "swift/weak-sensitive-data-hashing"
69+
or
70+
XxeConfig::isSink(sink) and result = "swift/xxe"
71+
or
72+
InsecureTlsConfig::isSink(sink) and result = "swift/insecure-tls"
73+
or
74+
ConstantSaltConfig::isSink(sink) and result = "swift/constant-salt"
75+
or
76+
InsufficientHashIterationsConfig::isSink(sink) and result = "swift/insufficient-hash-iterations"
77+
or
78+
PredicateInjectionConfig::isSink(sink) and result = "swift/predicate-injection"
79+
or
80+
StaticInitializationVectorConfig::isSink(sink) and result = "swift/static-initialization-vector"
81+
}
82+
83+
from DataFlow::Node n
84+
select n, "Sink for " + queryForSink(n)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @name Regular Expression Evaluations
3+
* @description List all regular expression evaluations found in the database.
4+
* @kind problem
5+
* @problem.severity info
6+
* @id swift/summary/regex-evals
7+
* @tags summary
8+
*/
9+
10+
import swift
11+
import codeql.swift.regex.Regex
12+
13+
from RegexEval e, string message, Expr regex
14+
where
15+
message = "Regular expression evaluation with source $@." and regex = e.getARegex()
16+
or
17+
message = "Regular expression evaluation with no identified source." and
18+
not exists(e.getARegex()) and
19+
regex = e
20+
select e, message, regex, regex.toString()

swift/ql/src/queries/Summary/SummaryStats.ql

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @name Summary statistics
2+
* @name Summary Statistics
33
* @description A table of summary statistics about a database.
44
* @kind table
55
* @id swift/summary/summary-statistics
@@ -9,32 +9,8 @@
99
import swift
1010
import codeql.swift.dataflow.FlowSources
1111
import codeql.swift.security.SensitiveExprs
12-
import codeql.swift.dataflow.DataFlow
13-
import codeql.swift.dataflow.TaintTracking
1412
import codeql.swift.regex.Regex
1513

16-
/**
17-
* A taint configuration for tainted data reaching any node.
18-
*/
19-
module TaintReachConfig implements DataFlow::ConfigSig {
20-
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
21-
22-
predicate isSink(DataFlow::Node node) { any() }
23-
}
24-
25-
module TaintReachFlow = TaintTracking::Global<TaintReachConfig>;
26-
27-
/**
28-
* Gets the total number of dataflow nodes that taint reaches (from any source).
29-
*/
30-
int taintedNodesCount() { result = count(DataFlow::Node n | TaintReachFlow::flowTo(n)) }
31-
32-
/**
33-
* Gets the proportion of dataflow nodes that taint reaches (from any source),
34-
* expressed as a count per million nodes.
35-
*/
36-
float taintReach() { result = (taintedNodesCount() * 1000000.0) / count(DataFlow::Node n) }
37-
3814
predicate statistic(string what, string value) {
3915
what = "Files" and value = count(File f).toString()
4016
or
@@ -52,13 +28,10 @@ predicate statistic(string what, string value) {
5228
or
5329
what = "Sensitive expressions" and value = count(SensitiveExpr e).toString()
5430
or
55-
what = "Dataflow nodes (total)" and value = count(DataFlow::Node n).toString()
56-
or
57-
what = "Dataflow nodes (tainted)" and value = taintedNodesCount().toString()
58-
or
59-
what = "Taint reach (per million nodes)" and value = taintReach().toString()
60-
or
6131
what = "Regular expression evals" and value = count(RegexEval e).toString()
32+
or
33+
what = "Regular expressions evaluated" and
34+
value = count(RegexEval e | | e.getARegex()).toString()
6235
}
6336

6437
from string what, string value
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @name Taint Reach
3+
* @description Calculates 'taint reach', a measure of how much of a database
4+
* is reached from flow sources, via taint flow. This can be
5+
* expensive to compute on large databases.
6+
* @kind table
7+
* @id swift/summary/taint-reach
8+
* @tags summary
9+
*/
10+
11+
import swift
12+
import codeql.swift.dataflow.FlowSources
13+
import codeql.swift.dataflow.DataFlow
14+
import codeql.swift.dataflow.TaintTracking
15+
16+
/**
17+
* A taint configuration for tainted data reaching any node.
18+
*/
19+
module TaintReachConfig implements DataFlow::ConfigSig {
20+
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
21+
22+
predicate isSink(DataFlow::Node node) { any() }
23+
}
24+
25+
module TaintReachFlow = TaintTracking::Global<TaintReachConfig>;
26+
27+
/**
28+
* Gets the total number of dataflow nodes that taint reaches (from any source).
29+
*/
30+
int taintedNodesCount() { result = count(DataFlow::Node n | TaintReachFlow::flowTo(n)) }
31+
32+
/**
33+
* Gets the proportion of dataflow nodes that taint reaches (from any source),
34+
* expressed as a count per million nodes.
35+
*/
36+
float taintReach() { result = (taintedNodesCount() * 1000000.0) / count(DataFlow::Node n) }
37+
38+
predicate statistic(string what, string value) {
39+
what = "Dataflow nodes (total)" and value = count(DataFlow::Node n).toString()
40+
or
41+
what = "Dataflow nodes (tainted)" and value = taintedNodesCount().toString()
42+
or
43+
what = "Taint reach (per million nodes)" and value = taintReach().toString()
44+
}
45+
46+
from string what, string value
47+
where statistic(what, value)
48+
select what, value

0 commit comments

Comments
 (0)