Skip to content

Commit fe1103d

Browse files
committed
add stubs, upgrade test to inline test, update test files
1 parent 7df59ff commit fe1103d

File tree

80 files changed

+2197
-356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2197
-356
lines changed

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

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,7 @@
1212
*/
1313

1414
import java
15-
import semmle.code.java.dataflow.FlowSources
16-
import experimental.semmle.code.java.security.FileAndFormRemoteSource
17-
import experimental.semmle.code.java.security.DecompressionBomb::DecompressionBomb
18-
import semmle.code.java.dataflow.TaintTracking
19-
20-
module DecompressionBombsConfig implements DataFlow::ConfigSig {
21-
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
22-
23-
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
24-
25-
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
26-
any(AdditionalStep ads).step(nodeFrom, nodeTo)
27-
}
28-
}
29-
30-
module DecompressionBombsFlow = TaintTracking::Global<DecompressionBombsConfig>;
31-
32-
import DecompressionBombsFlow::PathGraph
15+
import experimental.semmle.code.java.security.DecompressionBombQuery
3316

3417
from DecompressionBombsFlow::PathNode source, DecompressionBombsFlow::PathNode sink
3518
where DecompressionBombsFlow::flowPath(source, sink)

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,29 @@ module ApacheCommons {
222222
}
223223
}
224224

225+
/**
226+
* Gets `n1` and `n2` which `CompressorInputStream n2 = new CompressorStreamFactory().createCompressorInputStream(n1)`
227+
* or `ArchiveInputStream n2 = new ArchiveStreamFactory().createArchiveInputStream(n1)` or
228+
* `n1.read(n2)`,
229+
* second one is added because of sanitizer, we want to compare return value of each `read` or similar method
230+
* that whether there is a flow to a comparison between total read of decompressed stream and a constant value
231+
*/
232+
private class CompressorsAndArchiversAdditionalTaintStep extends DecompressionBomb::AdditionalStep
233+
{
234+
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
235+
exists(Call call |
236+
// Constructors
237+
(
238+
call.getCallee().getDeclaringType() = any(TypeCompressors t)
239+
or
240+
call.getCallee().getDeclaringType() = any(TypeArchivers t)
241+
) and
242+
call.getArgument(0) = n1.asExpr() and
243+
call = n2.asExpr()
244+
)
245+
}
246+
}
247+
225248
/**
226249
* The methods that read bytes and belong to `CompressorInputStream` or `ArchiveInputStream` Types
227250
*/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import semmle.code.java.dataflow.FlowSources
2+
import experimental.semmle.code.java.security.FileAndFormRemoteSource
3+
import semmle.code.java.dataflow.TaintTracking
4+
import experimental.semmle.code.java.security.DecompressionBomb::DecompressionBomb
5+
6+
module DecompressionBombsConfig implements DataFlow::ConfigSig {
7+
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
8+
9+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
10+
11+
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
12+
any(AdditionalStep ads).step(nodeFrom, nodeTo)
13+
}
14+
}
15+
16+
module DecompressionBombsFlow = TaintTracking::Global<DecompressionBombsConfig>;
17+
18+
import DecompressionBombsFlow::PathGraph
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import org.apache.commons.compress.archivers.ArchiveException;
2+
import org.apache.commons.compress.compressors.CompressorException;
3+
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.io.InputStreamReader;
7+
import java.io.BufferedReader;
8+
import java.net.Socket;
9+
import java.util.zip.DataFormatException;
10+
11+
public class Bombs {
12+
public void sendUserFileGood2(Socket sock) throws IOException {
13+
InputStream remoteFile = sock.getInputStream();
14+
// Zip
15+
ZipHandler.ZipInputStreamSafe2(remoteFile);
16+
ZipHandler.ZipInputStreamSafe(remoteFile);
17+
ZipHandler.ZipInputStreamUnsafe(remoteFile);
18+
ZipHandler.GZipInputStreamUnsafe(remoteFile);
19+
ZipHandler.InflaterInputStreamUnsafe(remoteFile);
20+
21+
BufferedReader filenameReader =
22+
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
23+
String filename = filenameReader.readLine();
24+
try {
25+
ZipHandler.InflaterUnsafe(filename.getBytes());
26+
} catch (DataFormatException e) {
27+
throw new RuntimeException(e);
28+
}
29+
try {
30+
ZipHandler.ZipFile1(filename);
31+
} catch (DataFormatException e) {
32+
throw new RuntimeException(e);
33+
}
34+
35+
// Zip4j
36+
Zip4jHandler.zip4jZipInputStream(remoteFile);
37+
Zip4jHandler.zip4jZipInputStreamSafe(remoteFile);
38+
// SnappyZip
39+
SnappyHandler.SnappyZipInputStream(remoteFile);
40+
// apache Commons
41+
CommonsCompressHandler.commonsCompressArchiveInputStream2(remoteFile);
42+
CommonsCompressHandler.commonsCompressorInputStream(remoteFile);
43+
try {
44+
CommonsCompressHandler.commonsCompressArchiveInputStream(remoteFile);
45+
CommonsCompressHandler.commonsCompressArchiveStreamFactory(remoteFile);
46+
} catch (ArchiveException e) {
47+
throw new RuntimeException(e);
48+
}
49+
try {
50+
CommonsCompressHandler.commonsCompressCompressorStreamFactory(remoteFile);
51+
} catch (CompressorException e) {
52+
throw new RuntimeException(e);
53+
}
54+
55+
}
56+
}
Lines changed: 108 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,128 @@
1-
import java.io.*;
1+
import java.io.InputStream;
2+
import java.io.OutputStream;
3+
import java.io.IOException;
4+
import java.io.File;
5+
import java.io.FileOutputStream;
6+
import java.io.BufferedInputStream;
27
import java.nio.file.Files;
38
import java.nio.file.Path;
4-
import org.apache.commons.compress.archivers.*;
9+
10+
import org.apache.commons.compress.archivers.ArchiveEntry;
11+
import org.apache.commons.compress.archivers.ArchiveException;
12+
import org.apache.commons.compress.archivers.ArchiveInputStream;
13+
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
514
import org.apache.commons.compress.compressors.CompressorException;
615
import org.apache.commons.compress.compressors.CompressorInputStream;
716
import org.apache.commons.compress.compressors.CompressorStreamFactory;
8-
import org.apache.commons.compress.compressors.gzip.*;
17+
import org.apache.commons.compress.compressors.lz4.*;
18+
import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
19+
import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream;
20+
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
21+
import org.apache.commons.compress.archivers.jar.JarArchiveInputStream;
22+
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
23+
import org.apache.commons.compress.compressors.lzma.LZMACompressorInputStream;
24+
import org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream;
25+
import org.apache.commons.compress.compressors.snappy.SnappyCompressorInputStream;
26+
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
27+
import org.apache.commons.compress.compressors.zstandard.ZstdCompressorInputStream;
28+
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
29+
import org.apache.commons.compress.compressors.brotli.BrotliCompressorInputStream;
30+
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
31+
import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream;
32+
import org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInputStream;
33+
import org.apache.commons.compress.compressors.z.ZCompressorInputStream;
934

1035
public class CommonsCompressHandler {
11-
public static void commonsCompressorInputStream(InputStream inputStream) throws IOException {
12-
BufferedInputStream in = new BufferedInputStream(inputStream);
13-
OutputStream out = Files.newOutputStream(Path.of("tmpfile"));
14-
GzipCompressorInputStream gzIn =
15-
new org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream(in);
16-
// for testing
17-
new org.apache.commons.compress.compressors.brotli.BrotliCompressorInputStream(in);
18-
new org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream(in);
19-
new org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream(in);
20-
new org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInputStream(in);
21-
new org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorInputStream(in);
22-
new org.apache.commons.compress.compressors.lzma.LZMACompressorInputStream(in);
23-
new org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream(in);
24-
new org.apache.commons.compress.compressors.snappy.SnappyCompressorInputStream(in);
25-
new org.apache.commons.compress.compressors.xz.XZCompressorInputStream(in);
26-
new org.apache.commons.compress.compressors.z.ZCompressorInputStream(in);
27-
new org.apache.commons.compress.compressors.zstandard.ZstdCompressorInputStream(in);
2836

29-
int buffersize = 4096;
30-
final byte[] buffer = new byte[buffersize];
31-
int n = 0;
32-
while (-1 != (n = gzIn.read(buffer))) {
33-
out.write(buffer, 0, n);
37+
static void commonsCompressArchiveInputStream(InputStream inputStream) throws ArchiveException {
38+
new ArArchiveInputStream(inputStream); // $bomb
39+
new ArjArchiveInputStream(inputStream); // $bomb
40+
new CpioArchiveInputStream(inputStream); // $bomb
41+
new JarArchiveInputStream(inputStream); // $bomb
42+
new ZipArchiveInputStream(inputStream); // $bomb
3443
}
35-
out.close();
36-
gzIn.close();
37-
}
3844

39-
static void commonsCompressArchiveInputStream(InputStream inputStream) throws ArchiveException {
40-
new org.apache.commons.compress.archivers.ar.ArArchiveInputStream(inputStream);
41-
new org.apache.commons.compress.archivers.arj.ArjArchiveInputStream(inputStream);
42-
new org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream(inputStream);
43-
new org.apache.commons.compress.archivers.jar.JarArchiveInputStream(inputStream);
44-
new org.apache.commons.compress.archivers.zip.ZipArchiveInputStream(inputStream);
45-
}
45+
public static void commonsCompressorInputStream(InputStream inputStream) throws IOException {
46+
BufferedInputStream in = new BufferedInputStream(inputStream);
47+
OutputStream out = Files.newOutputStream(Path.of("tmpfile"));
48+
GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in); // $bomb
49+
// for testing
50+
new BrotliCompressorInputStream(in); // $bomb
51+
new BZip2CompressorInputStream(in); // $bomb
52+
new DeflateCompressorInputStream(in); // $bomb
53+
new Deflate64CompressorInputStream(in); // $bomb
54+
new BlockLZ4CompressorInputStream(in); // $bomb
55+
new LZMACompressorInputStream(in); // $bomb
56+
new Pack200CompressorInputStream(in); // $bomb
57+
new SnappyCompressorInputStream(in); // $bomb
58+
new XZCompressorInputStream(in); // $bomb
59+
new ZCompressorInputStream(in); // $bomb
60+
new ZstdCompressorInputStream(in); // $bomb
4661

47-
static void commonsCompressArchiveInputStream2(InputStream inputStream) {
48-
byte[] readBuffer = new byte[4096];
49-
try (org.apache.commons.compress.archivers.zip.ZipArchiveInputStream zipInputStream =
50-
new org.apache.commons.compress.archivers.zip.ZipArchiveInputStream(inputStream)) {
51-
ArchiveEntry entry = null;
52-
while ((entry = zipInputStream.getNextEntry()) != null) {
53-
if (!zipInputStream.canReadEntryData(entry)) {
54-
continue;
62+
int buffersize = 4096;
63+
final byte[] buffer = new byte[buffersize];
64+
int n = 0;
65+
while (-1 != (n = gzIn.read(buffer))) {
66+
out.write(buffer, 0, n);
5567
}
56-
File f = new File("tmpfile");
57-
try (OutputStream outputStream = new FileOutputStream(f)) {
58-
int readLen;
59-
while ((readLen = zipInputStream.read(readBuffer)) != -1) { // BAD
60-
outputStream.write(readBuffer, 0, readLen);
61-
}
68+
out.close();
69+
gzIn.close();
70+
}
71+
72+
static void commonsCompressArchiveInputStream2(InputStream inputStream) {
73+
byte[] readBuffer = new byte[4096];
74+
try (org.apache.commons.compress.archivers.zip.ZipArchiveInputStream zipInputStream =
75+
new org.apache.commons.compress.archivers.zip.ZipArchiveInputStream(inputStream)) { // $bomb
76+
ArchiveEntry entry = null;
77+
while ((entry = zipInputStream.getNextEntry()) != null) {
78+
if (!zipInputStream.canReadEntryData(entry)) {
79+
continue;
80+
}
81+
File f = new File("tmpfile");
82+
try (OutputStream outputStream = new FileOutputStream(f)) {
83+
int readLen;
84+
while ((readLen = zipInputStream.read(readBuffer)) != -1) {
85+
outputStream.write(readBuffer, 0, readLen);
86+
}
87+
}
88+
}
89+
} catch (IOException e) {
90+
throw new RuntimeException(e);
6291
}
63-
}
64-
} catch (IOException e) {
65-
throw new RuntimeException(e);
6692
}
67-
}
6893

69-
static void commonsCompressArchiveStreamFactory(InputStream inputStream)
70-
throws IOException, ArchiveException {
71-
BufferedInputStream bin = new BufferedInputStream(inputStream);
72-
ArchiveInputStream zipInputStream = new ArchiveStreamFactory().createArchiveInputStream(bin);
73-
ArchiveEntry entry = null;
74-
byte[] readBuffer = new byte[4096];
75-
while ((entry = zipInputStream.getNextEntry()) != null) {
76-
if (!zipInputStream.canReadEntryData(entry)) {
77-
continue;
78-
}
79-
File f = new File("tmpfile");
80-
try (OutputStream outputStream = new FileOutputStream(f)) {
81-
int readLen;
82-
while ((readLen = zipInputStream.read(readBuffer)) != -1) { // BAD
83-
outputStream.write(readBuffer, 0, readLen);
94+
static void commonsCompressArchiveStreamFactory(InputStream inputStream)
95+
throws IOException, ArchiveException {
96+
BufferedInputStream bin = new BufferedInputStream(inputStream);
97+
ArchiveInputStream zipInputStream = new ArchiveStreamFactory().createArchiveInputStream(bin);
98+
ArchiveEntry entry = null;
99+
byte[] readBuffer = new byte[4096];
100+
while ((entry = zipInputStream.getNextEntry()) != null) {
101+
if (!zipInputStream.canReadEntryData(entry)) {
102+
continue;
103+
}
104+
File f = new File("tmpfile");
105+
try (OutputStream outputStream = new FileOutputStream(f)) {
106+
int readLen;
107+
while ((readLen = zipInputStream.read(readBuffer)) != -1) { // $bomb
108+
outputStream.write(readBuffer, 0, readLen);
109+
}
110+
}
84111
}
85-
}
86112
}
87-
}
88113

89-
static void commonsCompressCompressorStreamFactory(InputStream inputStream)
90-
throws IOException, CompressorException {
91-
BufferedInputStream bin = new BufferedInputStream(inputStream);
92-
CompressorInputStream in = new CompressorStreamFactory().createCompressorInputStream(bin);
93-
OutputStream out = Files.newOutputStream(Path.of("tmpfile"));
94-
int buffersize = 4096;
95-
final byte[] buffer = new byte[buffersize];
96-
int n = 0;
97-
while (-1 != (n = in.read(buffer))) { // BAD
98-
out.write(buffer, 0, n);
114+
static void commonsCompressCompressorStreamFactory(InputStream inputStream)
115+
throws IOException, CompressorException {
116+
BufferedInputStream bin = new BufferedInputStream(inputStream);
117+
CompressorInputStream in = new CompressorStreamFactory().createCompressorInputStream(bin);
118+
OutputStream out = Files.newOutputStream(Path.of("tmpfile"));
119+
int buffersize = 4096;
120+
final byte[] buffer = new byte[buffersize];
121+
int n = 0;
122+
while (-1 != (n = in.read(buffer))) { // $bomb
123+
out.write(buffer, 0, n);
124+
}
125+
out.close();
126+
in.close();
99127
}
100-
out.close();
101-
in.close();
102-
}
103128
}

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

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)