Skip to content

Commit b6d12f8

Browse files
committed
Ruby: configsig rb/zip-slip
1 parent ebf2a2e commit b6d12f8

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

ruby/ql/lib/codeql/ruby/experimental/ZipSlipQuery.qll

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ private import codeql.ruby.ApiGraphs
1212
/**
1313
* A taint-tracking configuration for reasoning about zip slip
1414
* vulnerabilities.
15+
* DEPRECATED: Use `ZipSlipFlow`
1516
*/
16-
class Configuration extends TaintTracking::Configuration {
17+
deprecated class Configuration extends TaintTracking::Configuration {
1718
Configuration() { this = "ZipSlip" }
1819

1920
override predicate isSource(DataFlow::Node source) { source instanceof ZipSlip::Source }
@@ -36,3 +37,30 @@ class Configuration extends TaintTracking::Configuration {
3637

3738
override predicate isSanitizer(DataFlow::Node node) { node instanceof ZipSlip::Sanitizer }
3839
}
40+
41+
private module ZipSlipConfig implements DataFlow::ConfigSig {
42+
predicate isSource(DataFlow::Node source) { source instanceof ZipSlip::Source }
43+
44+
predicate isSink(DataFlow::Node sink) { sink instanceof ZipSlip::Sink }
45+
46+
/**
47+
* This should actually be
48+
* `and cn = API::getTopLevelMember("Gem").getMember("Package").getMember("TarReader").getMember("Entry").getAMethodCall("full_name")` and similar for other classes
49+
* but I couldn't make it work so there's only check for the method name called on the entry. It is `full_name` for `Gem::Package::TarReader::Entry` and `Zlib`
50+
* and `name` for `Zip::File`
51+
*/
52+
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
53+
exists(DataFlow::CallNode cn |
54+
cn.getReceiver() = nodeFrom and
55+
cn.getMethodName() in ["full_name", "name"] and
56+
cn = nodeTo
57+
)
58+
}
59+
60+
predicate isBarrier(DataFlow::Node node) { node instanceof ZipSlip::Sanitizer }
61+
}
62+
63+
/**
64+
* Taint-tracking for reasoning about zip slip vulnerabilities.
65+
*/
66+
module ZipSlipFlow = TaintTracking::Global<ZipSlipConfig>;

ruby/ql/src/experimental/cwe-022-zipslip/ZipSlip.ql

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@
1212
* external/cwe/cwe-022
1313
*/
1414

15-
import ruby
1615
import codeql.ruby.experimental.ZipSlipQuery
17-
import DataFlow::PathGraph
16+
import ZipSlipFlow::PathGraph
1817

19-
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
20-
where cfg.hasFlowPath(source, sink)
18+
from ZipSlipFlow::PathNode source, ZipSlipFlow::PathNode sink
19+
where ZipSlipFlow::flowPath(source, sink)
2120
select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(),
2221
"potentially untrusted source"

ruby/ql/test/query-tests/experimental/cwe-022-ZipSlip/ZipSlip.expected

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,55 @@ edges
22
| zip_slip.rb:8:5:8:11 | tarfile | zip_slip.rb:9:5:9:11 | tarfile |
33
| zip_slip.rb:8:15:8:54 | call to new | zip_slip.rb:8:5:8:11 | tarfile |
44
| zip_slip.rb:9:5:9:11 | tarfile | zip_slip.rb:9:22:9:26 | entry |
5-
| zip_slip.rb:9:22:9:26 | entry | zip_slip.rb:10:19:10:33 | call to full_name |
5+
| zip_slip.rb:9:22:9:26 | entry | zip_slip.rb:10:19:10:23 | entry |
6+
| zip_slip.rb:10:19:10:23 | entry | zip_slip.rb:10:19:10:33 | call to full_name |
67
| zip_slip.rb:20:50:20:56 | tarfile | zip_slip.rb:21:7:21:13 | tarfile |
78
| zip_slip.rb:21:7:21:13 | tarfile | zip_slip.rb:21:30:21:34 | entry |
8-
| zip_slip.rb:21:30:21:34 | entry | zip_slip.rb:22:21:22:35 | call to full_name |
9+
| zip_slip.rb:21:30:21:34 | entry | zip_slip.rb:22:21:22:25 | entry |
10+
| zip_slip.rb:22:21:22:25 | entry | zip_slip.rb:22:21:22:35 | call to full_name |
911
| zip_slip.rb:46:5:46:24 | call to open | zip_slip.rb:46:35:46:39 | entry |
10-
| zip_slip.rb:46:35:46:39 | entry | zip_slip.rb:47:17:47:26 | call to name |
12+
| zip_slip.rb:46:35:46:39 | entry | zip_slip.rb:47:17:47:21 | entry |
13+
| zip_slip.rb:47:17:47:21 | entry | zip_slip.rb:47:17:47:26 | call to name |
1114
| zip_slip.rb:56:30:56:37 | zip_file | zip_slip.rb:57:7:57:14 | zip_file |
1215
| zip_slip.rb:57:7:57:14 | zip_file | zip_slip.rb:57:25:57:29 | entry |
13-
| zip_slip.rb:57:25:57:29 | entry | zip_slip.rb:58:19:58:28 | call to name |
16+
| zip_slip.rb:57:25:57:29 | entry | zip_slip.rb:58:19:58:23 | entry |
17+
| zip_slip.rb:58:19:58:23 | entry | zip_slip.rb:58:19:58:28 | call to name |
1418
| zip_slip.rb:90:5:90:8 | gzip | zip_slip.rb:91:11:91:14 | gzip |
1519
| zip_slip.rb:90:12:90:54 | call to open | zip_slip.rb:90:5:90:8 | gzip |
1620
| zip_slip.rb:91:11:91:14 | gzip | zip_slip.rb:97:42:97:56 | compressed_file |
1721
| zip_slip.rb:97:42:97:56 | compressed_file | zip_slip.rb:98:7:98:21 | compressed_file |
1822
| zip_slip.rb:98:7:98:21 | compressed_file | zip_slip.rb:98:32:98:36 | entry |
19-
| zip_slip.rb:98:32:98:36 | entry | zip_slip.rb:99:9:99:18 | entry_path |
23+
| zip_slip.rb:98:32:98:36 | entry | zip_slip.rb:99:22:99:26 | entry |
2024
| zip_slip.rb:99:9:99:18 | entry_path | zip_slip.rb:100:21:100:30 | entry_path |
25+
| zip_slip.rb:99:22:99:26 | entry | zip_slip.rb:99:22:99:36 | call to full_name |
26+
| zip_slip.rb:99:22:99:36 | call to full_name | zip_slip.rb:99:9:99:18 | entry_path |
2127
| zip_slip.rb:123:7:123:8 | gz | zip_slip.rb:124:7:124:8 | gz |
2228
| zip_slip.rb:123:12:123:34 | call to new | zip_slip.rb:123:7:123:8 | gz |
2329
| zip_slip.rb:124:7:124:8 | gz | zip_slip.rb:124:19:124:23 | entry |
24-
| zip_slip.rb:124:19:124:23 | entry | zip_slip.rb:125:9:125:18 | entry_path |
30+
| zip_slip.rb:124:19:124:23 | entry | zip_slip.rb:125:22:125:26 | entry |
2531
| zip_slip.rb:125:9:125:18 | entry_path | zip_slip.rb:126:21:126:30 | entry_path |
32+
| zip_slip.rb:125:22:125:26 | entry | zip_slip.rb:125:22:125:36 | call to full_name |
33+
| zip_slip.rb:125:22:125:36 | call to full_name | zip_slip.rb:125:9:125:18 | entry_path |
2634
nodes
2735
| zip_slip.rb:8:5:8:11 | tarfile | semmle.label | tarfile |
2836
| zip_slip.rb:8:15:8:54 | call to new | semmle.label | call to new |
2937
| zip_slip.rb:9:5:9:11 | tarfile | semmle.label | tarfile |
3038
| zip_slip.rb:9:22:9:26 | entry | semmle.label | entry |
39+
| zip_slip.rb:10:19:10:23 | entry | semmle.label | entry |
3140
| zip_slip.rb:10:19:10:33 | call to full_name | semmle.label | call to full_name |
3241
| zip_slip.rb:20:50:20:56 | tarfile | semmle.label | tarfile |
3342
| zip_slip.rb:21:7:21:13 | tarfile | semmle.label | tarfile |
3443
| zip_slip.rb:21:30:21:34 | entry | semmle.label | entry |
44+
| zip_slip.rb:22:21:22:25 | entry | semmle.label | entry |
3545
| zip_slip.rb:22:21:22:35 | call to full_name | semmle.label | call to full_name |
3646
| zip_slip.rb:46:5:46:24 | call to open | semmle.label | call to open |
3747
| zip_slip.rb:46:35:46:39 | entry | semmle.label | entry |
48+
| zip_slip.rb:47:17:47:21 | entry | semmle.label | entry |
3849
| zip_slip.rb:47:17:47:26 | call to name | semmle.label | call to name |
3950
| zip_slip.rb:56:30:56:37 | zip_file | semmle.label | zip_file |
4051
| zip_slip.rb:57:7:57:14 | zip_file | semmle.label | zip_file |
4152
| zip_slip.rb:57:25:57:29 | entry | semmle.label | entry |
53+
| zip_slip.rb:58:19:58:23 | entry | semmle.label | entry |
4254
| zip_slip.rb:58:19:58:28 | call to name | semmle.label | call to name |
4355
| zip_slip.rb:90:5:90:8 | gzip | semmle.label | gzip |
4456
| zip_slip.rb:90:12:90:54 | call to open | semmle.label | call to open |
@@ -47,12 +59,16 @@ nodes
4759
| zip_slip.rb:98:7:98:21 | compressed_file | semmle.label | compressed_file |
4860
| zip_slip.rb:98:32:98:36 | entry | semmle.label | entry |
4961
| zip_slip.rb:99:9:99:18 | entry_path | semmle.label | entry_path |
62+
| zip_slip.rb:99:22:99:26 | entry | semmle.label | entry |
63+
| zip_slip.rb:99:22:99:36 | call to full_name | semmle.label | call to full_name |
5064
| zip_slip.rb:100:21:100:30 | entry_path | semmle.label | entry_path |
5165
| zip_slip.rb:123:7:123:8 | gz | semmle.label | gz |
5266
| zip_slip.rb:123:12:123:34 | call to new | semmle.label | call to new |
5367
| zip_slip.rb:124:7:124:8 | gz | semmle.label | gz |
5468
| zip_slip.rb:124:19:124:23 | entry | semmle.label | entry |
5569
| zip_slip.rb:125:9:125:18 | entry_path | semmle.label | entry_path |
70+
| zip_slip.rb:125:22:125:26 | entry | semmle.label | entry |
71+
| zip_slip.rb:125:22:125:36 | call to full_name | semmle.label | call to full_name |
5672
| zip_slip.rb:126:21:126:30 | entry_path | semmle.label | entry_path |
5773
subpaths
5874
#select

0 commit comments

Comments
 (0)