Skip to content

Commit 7689db7

Browse files
committed
change apache commons sink
1 parent 1b97804 commit 7689db7

File tree

3 files changed

+77
-26
lines changed

3 files changed

+77
-26
lines changed

java/ql/src/experimental/semmle/code/java/security/DecompressionBomb.qll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,30 @@ module ApacheCommons {
156156
this.getCallee().hasName(["read", "readNBytes", "readAllBytes"])
157157
}
158158
}
159+
160+
/**
161+
* Gets `n1` and `n2` which `GzipCompressorInputStream n2 = new GzipCompressorInputStream(n1)`
162+
*/
163+
private class CompressorsAndArchiversAdditionalTaintStep extends DecompressionBomb::AdditionalStep
164+
{
165+
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
166+
exists(Call call |
167+
// Constructors
168+
call.getCallee().getDeclaringType() instanceof TypeCompressors and
169+
call.getArgument(0) = n1.asExpr() and
170+
call = n2.asExpr()
171+
)
172+
}
173+
}
174+
175+
predicate step(DataFlow::Node n1, DataFlow::Node n2) {
176+
exists(Call call |
177+
// Constructors
178+
call.getCallee().getDeclaringType() instanceof TypeCompressors and
179+
call.getArgument(0) = n1.asExpr() and
180+
call = n2.asExpr()
181+
)
182+
}
159183
}
160184

161185
/**
@@ -191,6 +215,25 @@ module ApacheCommons {
191215
this.getCallee().hasName(["read", "readNBytes", "readAllBytes"])
192216
}
193217
}
218+
219+
/**
220+
* Gets `n1` and `n2` which `CompressorInputStream n2 = new CompressorStreamFactory().createCompressorInputStream(n1)`
221+
* or `ArchiveInputStream n2 = new ArchiveStreamFactory().createArchiveInputStream(n1)` or
222+
* `n1.read(n2)`,
223+
* second one is added because of sanitizer, we want to compare return value of each `read` or similar method
224+
* that whether there is a flow to a comparison between total read of decompressed stream and a constant value
225+
*/
226+
private class CompressorsAndArchiversAdditionalTaintStep extends DecompressionBomb::AdditionalStep
227+
{
228+
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
229+
exists(Call call |
230+
// Constructors
231+
call.getCallee().getDeclaringType() instanceof TypeArchivers and
232+
call.getArgument(0) = n1.asExpr() and
233+
call = n2.asExpr()
234+
)
235+
}
236+
}
194237
}
195238

196239
/**

java/ql/test/experimental/query-tests/security/CWE-522-DecompressionBombs/Bombs.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public void sendUserFileGood2(Socket sock) throws IOException {
3838
// SnappyZip
3939
SnappyHandler.SnappyZipInputStream(remoteFile);
4040
// apache Commons
41-
CommonsCompressHandler.commonsCompressArchiveInputStream2(remoteFile);
4241
CommonsCompressHandler.commonsCompressorInputStream(remoteFile);
4342
try {
4443
CommonsCompressHandler.commonsCompressArchiveInputStream(remoteFile);

java/ql/test/experimental/query-tests/security/CWE-522-DecompressionBombs/CommonsCompressHandler.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,36 +34,45 @@
3434

3535
public class CommonsCompressHandler {
3636

37-
static void commonsCompressArchiveInputStream(InputStream inputStream) throws ArchiveException {
38-
new ArArchiveInputStream(inputStream); // $ hasTaintFlow="inputStream"
39-
new ArjArchiveInputStream(inputStream); // $ hasTaintFlow="inputStream"
40-
new CpioArchiveInputStream(inputStream); // $ hasTaintFlow="inputStream"
41-
new JarArchiveInputStream(inputStream); // $ hasTaintFlow="inputStream"
42-
new ZipArchiveInputStream(inputStream); // $ hasTaintFlow="inputStream"
43-
}
44-
4537
public static void commonsCompressorInputStream(InputStream inputStream) throws IOException {
4638
BufferedInputStream in = new BufferedInputStream(inputStream);
4739
OutputStream out = Files.newOutputStream(Path.of("tmpfile"));
48-
GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in); // $ hasTaintFlow="in"
49-
// for testing
50-
new BrotliCompressorInputStream(in); // $ hasTaintFlow="in"
51-
new BZip2CompressorInputStream(in); // $ hasTaintFlow="in"
52-
new DeflateCompressorInputStream(in); // $ hasTaintFlow="in"
53-
new Deflate64CompressorInputStream(in); // $ hasTaintFlow="in"
54-
new BlockLZ4CompressorInputStream(in); // $ hasTaintFlow="in"
55-
new LZMACompressorInputStream(in); // $ hasTaintFlow="in"
56-
new Pack200CompressorInputStream(in); // $ hasTaintFlow="in"
57-
new SnappyCompressorInputStream(in); // $ hasTaintFlow="in"
58-
new XZCompressorInputStream(in); // $ hasTaintFlow="in"
59-
new ZCompressorInputStream(in); // $ hasTaintFlow="in"
60-
new ZstdCompressorInputStream(in); // $ hasTaintFlow="in"
40+
GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in);
41+
// Also, the `new GzipCompressorInputStream(in)` can be the following:
42+
// new BrotliCompressorInputStream(in);
43+
// new BZip2CompressorInputStream(in);
44+
// new DeflateCompressorInputStream(in);
45+
// new Deflate64CompressorInputStream(in);
46+
// new BlockLZ4CompressorInputStream(in);
47+
// new LZMACompressorInputStream(in);
48+
// new Pack200CompressorInputStream(in);
49+
// new SnappyCompressorInputStream(in);
50+
// new XZCompressorInputStream(in);
51+
// new ZCompressorInputStream(in);
52+
// new ZstdCompressorInputStream(in);
53+
54+
int buffersize = 4096;
55+
final byte[] buffer = new byte[buffersize];
56+
int n = 0;
57+
while (-1 != (n = gzIn.read(buffer))) { // $ hasTaintFlow="gzIn"
58+
out.write(buffer, 0, n);
59+
}
60+
out.close();
61+
gzIn.close();
6162
}
6263

63-
static void commonsCompressArchiveInputStream2(InputStream inputStream) {
64+
static void commonsCompressArchiveInputStream(InputStream inputStream) {
6465
byte[] readBuffer = new byte[4096];
65-
try (org.apache.commons.compress.archivers.zip.ZipArchiveInputStream zipInputStream =
66-
new org.apache.commons.compress.archivers.zip.ZipArchiveInputStream(inputStream)) { // $ hasTaintFlow="inputStream"
66+
67+
// Also, the `new ZipArchiveInputStream(inputStream)` can be the following:
68+
// new ArArchiveInputStream(inputStream);
69+
// new ArjArchiveInputStream(inputStream);
70+
// new CpioArchiveInputStream(inputStream);
71+
// new JarArchiveInputStream(inputStream);
72+
// new ZipArchiveInputStream(inputStream);
73+
74+
try (ZipArchiveInputStream zipInputStream =
75+
new ZipArchiveInputStream(inputStream)) {
6776
ArchiveEntry entry = null;
6877
while ((entry = zipInputStream.getNextEntry()) != null) {
6978
if (!zipInputStream.canReadEntryData(entry)) {
@@ -72,7 +81,7 @@ static void commonsCompressArchiveInputStream2(InputStream inputStream) {
7281
File f = new File("tmpfile");
7382
try (OutputStream outputStream = new FileOutputStream(f)) {
7483
int readLen;
75-
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
84+
while ((readLen = zipInputStream.read(readBuffer)) != -1) { // $ hasTaintFlow="zipInputStream"
7685
outputStream.write(readBuffer, 0, readLen);
7786
}
7887
}

0 commit comments

Comments
 (0)