Skip to content

Commit 77dcd68

Browse files
committed
v2
1 parent d06444e commit 77dcd68

File tree

2 files changed

+22
-66
lines changed

2 files changed

+22
-66
lines changed

javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/DecompressionBombs.ql

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,19 @@ class BombConfiguration extends TaintTracking::Configuration {
3737
not exists(source.getALocalSource().getStringValue())
3838
)
3939
or
40-
exists(AstNode e |
41-
e =
42-
API::moduleImport("tar")
43-
.getMember(["x", "extract"])
44-
.getParameter(0)
45-
.asSink()
46-
.asExpr()
47-
.(ObjectExpr)
48-
.getAChild()
49-
.(Property)
50-
|
51-
source.asExpr() = e.getAChild() and
52-
e.getAChild*().(Label).getName() = "file" and
53-
not source.getALocalSource().mayHaveStringValue(_)
54-
)
40+
source =
41+
API::moduleImport("tar")
42+
.getMember(["x", "extract"])
43+
.getParameter(0)
44+
.getMember("file")
45+
.asSink() and
46+
not source.getALocalSource().mayHaveStringValue(_)
5547
}
5648

5749
override predicate isSink(DataFlow::Node sink) {
5850
// jszip
5951
exists(API::Node loadAsync | loadAsync = API::moduleImport("jszip").getMember("loadAsync") |
60-
sink = loadAsync.getParameter(0).asSink() and jsZipsanitizer(loadAsync)
52+
sink = loadAsync.getParameter(0).asSink() and not jsZipsanitizer(loadAsync)
6153
)
6254
or
6355
// node-tar
@@ -69,32 +61,17 @@ class BombConfiguration extends TaintTracking::Configuration {
6961
sink = tarExtract.getACall()
7062
or
7163
// tar.x({file: filename})
72-
// and we don't have a "maxReadSize: ANum" option
73-
sink.asExpr() =
74-
tarExtract
75-
.getParameter(0)
76-
.asSink()
77-
.asExpr()
78-
.(ObjectExpr)
79-
.getAChild()
80-
.(Property)
81-
.getAChild*() and
82-
tarExtract
83-
.getParameter(0)
84-
.asSink()
85-
.asExpr()
86-
.(ObjectExpr)
87-
.getAChild()
88-
.(Property)
89-
.getAChild*()
90-
.(Label)
91-
.getName() = "file"
64+
sink = tarExtract.getParameter(0).getMember("file").asSink()
65+
or
66+
// tar.x({file: filename})
67+
sink = tarExtract.getParameter(0).getMember("file").asSink()
9268
) and
93-
nodeTarSanitizer(tarExtract)
69+
// and there shouldn't be a "maxReadSize: ANum" option
70+
not nodeTarSanitizer(tarExtract)
9471
)
9572
or
9673
// zlib
97-
// we don't have a "maxOutputLength: ANum" option
74+
// there shouldn't be a "maxOutputLength: ANumber" option
9875
exists(API::Node zlib |
9976
zlib =
10077
API::moduleImport("zlib")
@@ -103,7 +80,7 @@ class BombConfiguration extends TaintTracking::Configuration {
10380
"createInflateRaw"
10481
]) and
10582
sink = zlib.getACall() and
106-
zlibSanitizer(zlib, 0)
83+
not zlibSanitizer(zlib.getParameter(0))
10784
or
10885
zlib =
10986
API::moduleImport("zlib")
@@ -112,7 +89,7 @@ class BombConfiguration extends TaintTracking::Configuration {
11289
"brotliDecompressSync", "inflateSync", "inflateRawSync", "inflate", "inflateRaw"
11390
]) and
11491
sink = zlib.getACall().getArgument(0) and
115-
zlibSanitizer(zlib, 1)
92+
not zlibSanitizer(zlib.getParameter(1))
11693
)
11794
or
11895
// pako
@@ -189,7 +166,6 @@ class BombConfiguration extends TaintTracking::Configuration {
189166
)
190167
or
191168
// pred.pipe(succ)
192-
// I saw many instances like response.pipe(succ) which I couldn't exactly model this pattern
193169
exists(DataFlow::MethodCallNode n |
194170
n.getMethodName() = "pipe" and
195171
succ = n.getArgument(0) and
@@ -200,34 +176,14 @@ class BombConfiguration extends TaintTracking::Configuration {
200176
}
201177

202178
predicate nodeTarSanitizer(API::Node tarExtract) {
203-
not tarExtract
204-
.getParameter(0)
205-
.asSink()
206-
.asExpr()
207-
.(ObjectExpr)
208-
.getAChild()
209-
.(Property)
210-
.getAChild*()
211-
.(Label)
212-
.getName() = "maxReadSize"
179+
exists(tarExtract.getParameter(0).getMember("maxReadSize"))
213180
}
214181

215182
predicate jsZipsanitizer(API::Node loadAsync) {
216-
not exists(loadAsync.getASuccessor*().getMember("_data").getMember("uncompressedSize"))
183+
exists(loadAsync.getASuccessor*().getMember("_data").getMember("uncompressedSize"))
217184
}
218185

219-
predicate zlibSanitizer(API::Node zlib, int numOfParameter) {
220-
numOfParameter = [0, 1] and
221-
not zlib.getParameter(numOfParameter)
222-
.asSink()
223-
.asExpr()
224-
.(ObjectExpr)
225-
.getAChild()
226-
.(Property)
227-
.getAChild*()
228-
.(Label)
229-
.getName() = "maxOutputLength"
230-
}
186+
predicate zlibSanitizer(API::Node zlib) { exists(zlib.getMember("maxOutputLength")) }
231187

232188
from BombConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
233189
where cfg.hasFlowPath(source, sink)

javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/ReadableAdditionalStep.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ predicate genaralStreamPipeAdditionalTaintStep(
4242
}
4343

4444
predicate streamPipelineAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
45-
// this step connect the a pipe parameter to the next parameter
45+
// this step connect the a pipeline parameter to the next pipeline parameter
4646
exists(API::Node cn, int i |
4747
i in [0 .. 10] and
4848
cn = nodeJsStream().getMember("pipeline")
@@ -51,7 +51,7 @@ predicate streamPipelineAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node
5151
succ = cn.getParameter(i + 1).asSink()
5252
)
5353
or
54-
// this step connect the first pipe parameter to the next parameter
54+
// this step connect the first pipeline parameter to the next parameters
5555
exists(API::Node cn, int i |
5656
i in [1 .. 10] and
5757
cn = nodeJsStream().getMember("pipeline")

0 commit comments

Comments
 (0)