Skip to content

Commit 1936935

Browse files
committed
add Inflater
1 parent 45499b0 commit 1936935

1 file changed

Lines changed: 51 additions & 8 deletions

File tree

java/ql/src/experimental/Security/CWE/CWE-522-DecompressionBombs/DecompressionBomb.ql

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/**
2-
* @name User-controlled file decompression
3-
* @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous
2+
* @name Uncontrolled file decompression
3+
* @description Uncontrolled data that flows into decompression library APIs without checking the compression rate is dangerous
44
* @kind path-problem
55
* @problem.severity error
66
* @security-severity 7.8
77
* @precision high
8-
* @id java/user-controlled-file-decompression
8+
* @id java/uncontrolled-file-decompression
99
* @tags security
1010
* experimental
1111
* external/cwe/cwe-409
@@ -300,19 +300,55 @@ module Zip4j {
300300
}
301301

302302
module Zip {
303-
class TypeZipInputStream extends RefType {
304-
TypeZipInputStream() {
303+
class TypeInputStream extends RefType {
304+
TypeInputStream() {
305305
this.getASupertype*()
306306
.hasQualifiedName("java.util.zip",
307307
["ZipInputStream", "GZIPInputStream", "InflaterInputStream"])
308308
}
309309
}
310310

311+
class TypeInflator extends RefType {
312+
TypeInflator() { this.hasQualifiedName("java.util.zip", "Inflater") }
313+
}
314+
315+
predicate inflatorAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
316+
// inflater.inflate(n2)
317+
exists(MethodAccess ma |
318+
ma.getReceiverType() instanceof TypeInflator and
319+
ma.getArgument(0) = n2.asExpr() and
320+
ma.getQualifier() = n1.asExpr() and
321+
ma.getCallee().hasName("inflate")
322+
)
323+
or
324+
// Inflater inflater = new Inflater();
325+
// n2 = inflater.setInput(n1)
326+
exists(MethodAccess ma |
327+
ma.getReceiverType() instanceof TypeInflator and
328+
n1.asExpr() = ma.getArgument(0) and
329+
n2.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = ma.getQualifier() and
330+
ma.getCallee().hasName("setInput")
331+
)
332+
}
333+
334+
class InflateCall extends MethodAccess {
335+
InflateCall() {
336+
this.getReceiverType() instanceof TypeInflator and
337+
this.getCallee().hasName("inflate")
338+
}
339+
340+
Expr getAWriteArgument() { result = this.getArgument(0) }
341+
342+
// look at Zip4j comments for this method
343+
predicate isControlledRead() { none() }
344+
}
345+
346+
// InflaterInputStream Izis = new InflaterInputStream(inputStream)
311347
predicate inputStreamAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
312348
exists(Call call |
313349
(
314-
call.getCallee().getDeclaringType() instanceof TypeZipInputStream or
315-
call.(MethodAccess).getReceiverType() instanceof TypeZipInputStream
350+
call.getCallee().getDeclaringType() instanceof TypeInputStream or
351+
call.(MethodAccess).getReceiverType() instanceof TypeInputStream
316352
) and
317353
call.getArgument(0) = n1.asExpr() and
318354
call = n2.asExpr()
@@ -321,7 +357,7 @@ module Zip {
321357

322358
class ReadInputStreamCall extends MethodAccess {
323359
ReadInputStreamCall() {
324-
this.getReceiverType() instanceof TypeZipInputStream and
360+
this.getReceiverType() instanceof TypeInputStream and
325361
this.getCallee().hasName(["read", "readNBytes", "readAllBytes"])
326362
}
327363

@@ -369,6 +405,9 @@ module DecompressionBombsConfig implements DataFlow::StateConfigSig {
369405
*/
370406
predicate isSink(DataFlow::Node sink, FlowState state) {
371407
(
408+
sink.asExpr() = any(Zip::InflateCall r).getAWriteArgument() and
409+
state = "Zip"
410+
or
372411
exists(CommonsIO::IOUtils ma |
373412
sink.asExpr() = ma.getArgument(0) and
374413
state = ["Zip4j", "Zip", "ApacheCommons", "XserialSnappy"]
@@ -397,6 +436,10 @@ module DecompressionBombsConfig implements DataFlow::StateConfigSig {
397436
predicate isAdditionalFlowStep(
398437
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
399438
) {
439+
Zip::inflatorAdditionalTaintStep(nodeFrom, nodeTo) and
440+
stateFrom = "Zip" and
441+
stateTo = "Zip"
442+
or
400443
(
401444
Zip::inputStreamAdditionalTaintStep(nodeFrom, nodeTo) and
402445
stateFrom = "Zip"

0 commit comments

Comments
 (0)