Ruby: configsig rb/zip-slip

This commit is contained in:
Alex Ford
2023-09-03 16:28:20 +01:00
parent ebf2a2e1f5
commit b6d12f8b1c
3 changed files with 54 additions and 11 deletions

View File

@@ -12,8 +12,9 @@ private import codeql.ruby.ApiGraphs
/**
* A taint-tracking configuration for reasoning about zip slip
* vulnerabilities.
* DEPRECATED: Use `ZipSlipFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ZipSlip" }
override predicate isSource(DataFlow::Node source) { source instanceof ZipSlip::Source }
@@ -36,3 +37,30 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof ZipSlip::Sanitizer }
}
private module ZipSlipConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ZipSlip::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof ZipSlip::Sink }
/**
* This should actually be
* `and cn = API::getTopLevelMember("Gem").getMember("Package").getMember("TarReader").getMember("Entry").getAMethodCall("full_name")` and similar for other classes
* 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`
* and `name` for `Zip::File`
*/
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(DataFlow::CallNode cn |
cn.getReceiver() = nodeFrom and
cn.getMethodName() in ["full_name", "name"] and
cn = nodeTo
)
}
predicate isBarrier(DataFlow::Node node) { node instanceof ZipSlip::Sanitizer }
}
/**
* Taint-tracking for reasoning about zip slip vulnerabilities.
*/
module ZipSlipFlow = TaintTracking::Global<ZipSlipConfig>;

View File

@@ -12,11 +12,10 @@
* external/cwe/cwe-022
*/
import ruby
import codeql.ruby.experimental.ZipSlipQuery
import DataFlow::PathGraph
import ZipSlipFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from ZipSlipFlow::PathNode source, ZipSlipFlow::PathNode sink
where ZipSlipFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(),
"potentially untrusted source"

View File

@@ -2,43 +2,55 @@ edges
| zip_slip.rb:8:5:8:11 | tarfile | zip_slip.rb:9:5:9:11 | tarfile |
| zip_slip.rb:8:15:8:54 | call to new | zip_slip.rb:8:5:8:11 | tarfile |
| zip_slip.rb:9:5:9:11 | tarfile | zip_slip.rb:9:22:9:26 | entry |
| zip_slip.rb:9:22:9:26 | entry | zip_slip.rb:10:19:10:33 | call to full_name |
| zip_slip.rb:9:22:9:26 | entry | zip_slip.rb:10:19:10:23 | entry |
| zip_slip.rb:10:19:10:23 | entry | zip_slip.rb:10:19:10:33 | call to full_name |
| zip_slip.rb:20:50:20:56 | tarfile | zip_slip.rb:21:7:21:13 | tarfile |
| zip_slip.rb:21:7:21:13 | tarfile | zip_slip.rb:21:30:21:34 | entry |
| zip_slip.rb:21:30:21:34 | entry | zip_slip.rb:22:21:22:35 | call to full_name |
| zip_slip.rb:21:30:21:34 | entry | zip_slip.rb:22:21:22:25 | entry |
| zip_slip.rb:22:21:22:25 | entry | zip_slip.rb:22:21:22:35 | call to full_name |
| zip_slip.rb:46:5:46:24 | call to open | zip_slip.rb:46:35:46:39 | entry |
| zip_slip.rb:46:35:46:39 | entry | zip_slip.rb:47:17:47:26 | call to name |
| zip_slip.rb:46:35:46:39 | entry | zip_slip.rb:47:17:47:21 | entry |
| zip_slip.rb:47:17:47:21 | entry | zip_slip.rb:47:17:47:26 | call to name |
| zip_slip.rb:56:30:56:37 | zip_file | zip_slip.rb:57:7:57:14 | zip_file |
| zip_slip.rb:57:7:57:14 | zip_file | zip_slip.rb:57:25:57:29 | entry |
| zip_slip.rb:57:25:57:29 | entry | zip_slip.rb:58:19:58:28 | call to name |
| zip_slip.rb:57:25:57:29 | entry | zip_slip.rb:58:19:58:23 | entry |
| zip_slip.rb:58:19:58:23 | entry | zip_slip.rb:58:19:58:28 | call to name |
| zip_slip.rb:90:5:90:8 | gzip | zip_slip.rb:91:11:91:14 | gzip |
| zip_slip.rb:90:12:90:54 | call to open | zip_slip.rb:90:5:90:8 | gzip |
| zip_slip.rb:91:11:91:14 | gzip | zip_slip.rb:97:42:97:56 | compressed_file |
| zip_slip.rb:97:42:97:56 | compressed_file | zip_slip.rb:98:7:98:21 | compressed_file |
| zip_slip.rb:98:7:98:21 | compressed_file | zip_slip.rb:98:32:98:36 | entry |
| zip_slip.rb:98:32:98:36 | entry | zip_slip.rb:99:9:99:18 | entry_path |
| zip_slip.rb:98:32:98:36 | entry | zip_slip.rb:99:22:99:26 | entry |
| zip_slip.rb:99:9:99:18 | entry_path | zip_slip.rb:100:21:100:30 | entry_path |
| zip_slip.rb:99:22:99:26 | entry | zip_slip.rb:99:22:99:36 | call to full_name |
| zip_slip.rb:99:22:99:36 | call to full_name | zip_slip.rb:99:9:99:18 | entry_path |
| zip_slip.rb:123:7:123:8 | gz | zip_slip.rb:124:7:124:8 | gz |
| zip_slip.rb:123:12:123:34 | call to new | zip_slip.rb:123:7:123:8 | gz |
| zip_slip.rb:124:7:124:8 | gz | zip_slip.rb:124:19:124:23 | entry |
| zip_slip.rb:124:19:124:23 | entry | zip_slip.rb:125:9:125:18 | entry_path |
| zip_slip.rb:124:19:124:23 | entry | zip_slip.rb:125:22:125:26 | entry |
| zip_slip.rb:125:9:125:18 | entry_path | zip_slip.rb:126:21:126:30 | entry_path |
| zip_slip.rb:125:22:125:26 | entry | zip_slip.rb:125:22:125:36 | call to full_name |
| zip_slip.rb:125:22:125:36 | call to full_name | zip_slip.rb:125:9:125:18 | entry_path |
nodes
| zip_slip.rb:8:5:8:11 | tarfile | semmle.label | tarfile |
| zip_slip.rb:8:15:8:54 | call to new | semmle.label | call to new |
| zip_slip.rb:9:5:9:11 | tarfile | semmle.label | tarfile |
| zip_slip.rb:9:22:9:26 | entry | semmle.label | entry |
| zip_slip.rb:10:19:10:23 | entry | semmle.label | entry |
| zip_slip.rb:10:19:10:33 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:20:50:20:56 | tarfile | semmle.label | tarfile |
| zip_slip.rb:21:7:21:13 | tarfile | semmle.label | tarfile |
| zip_slip.rb:21:30:21:34 | entry | semmle.label | entry |
| zip_slip.rb:22:21:22:25 | entry | semmle.label | entry |
| zip_slip.rb:22:21:22:35 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:46:5:46:24 | call to open | semmle.label | call to open |
| zip_slip.rb:46:35:46:39 | entry | semmle.label | entry |
| zip_slip.rb:47:17:47:21 | entry | semmle.label | entry |
| zip_slip.rb:47:17:47:26 | call to name | semmle.label | call to name |
| zip_slip.rb:56:30:56:37 | zip_file | semmle.label | zip_file |
| zip_slip.rb:57:7:57:14 | zip_file | semmle.label | zip_file |
| zip_slip.rb:57:25:57:29 | entry | semmle.label | entry |
| zip_slip.rb:58:19:58:23 | entry | semmle.label | entry |
| zip_slip.rb:58:19:58:28 | call to name | semmle.label | call to name |
| zip_slip.rb:90:5:90:8 | gzip | semmle.label | gzip |
| zip_slip.rb:90:12:90:54 | call to open | semmle.label | call to open |
@@ -47,12 +59,16 @@ nodes
| zip_slip.rb:98:7:98:21 | compressed_file | semmle.label | compressed_file |
| zip_slip.rb:98:32:98:36 | entry | semmle.label | entry |
| zip_slip.rb:99:9:99:18 | entry_path | semmle.label | entry_path |
| zip_slip.rb:99:22:99:26 | entry | semmle.label | entry |
| zip_slip.rb:99:22:99:36 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:100:21:100:30 | entry_path | semmle.label | entry_path |
| zip_slip.rb:123:7:123:8 | gz | semmle.label | gz |
| zip_slip.rb:123:12:123:34 | call to new | semmle.label | call to new |
| zip_slip.rb:124:7:124:8 | gz | semmle.label | gz |
| zip_slip.rb:124:19:124:23 | entry | semmle.label | entry |
| zip_slip.rb:125:9:125:18 | entry_path | semmle.label | entry_path |
| zip_slip.rb:125:22:125:26 | entry | semmle.label | entry |
| zip_slip.rb:125:22:125:36 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:126:21:126:30 | entry_path | semmle.label | entry_path |
subpaths
#select