Skip to content

Commit 92c6170

Browse files
committed
C++: Simplify QLhelp
One good and one bad example suffices to get the point across, and makes the help more readable. The examples also do not have to be complete.
1 parent 2369b18 commit 92c6170

File tree

3 files changed

+23
-192
lines changed

3 files changed

+23
-192
lines changed

cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.qhelp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"qhelp.dtd">
44
<qhelp>
55
<overview>
6-
<p>Extracting Compressed files with any compression algorithm like gzip can cause to denial of service attacks.</p>
7-
<p>Attackers can compress a huge file which created by repeated similiar byte and convert it to a small compressed file.</p>
6+
<p>Extracting Compressed files with any compression algorithm like gzip can cause denial of service attacks.</p>
7+
<p>Attackers can compress a huge file consisting of repeated similiar bytes into a small compressed file.</p>
88
</overview>
99
<recommendation>
1010

@@ -14,12 +14,12 @@
1414
<example>
1515

1616
<p>
17-
Reading uncompressed Gzip file within a loop and check for a threshold size in each cycle.
17+
Reading an uncompressed Gzip file within a loop and check for a threshold size in each cycle.
1818
</p>
1919
<sample src="example_good.cpp"/>
2020

2121
<p>
22-
An Unsafe Approach can be this example which we don't check for uncompressed size.
22+
The following example is unsafe, as we do not check the uncompressed size.
2323
</p>
2424
<sample src="example_bad.cpp" />
2525

@@ -28,11 +28,11 @@ An Unsafe Approach can be this example which we don't check for uncompressed siz
2828
<references>
2929

3030
<li>
31-
<a href="https://zlib.net/manual.html">Zlib Documentation</a>
31+
<a href="https://zlib.net/manual.html">Zlib documentation</a>
3232
</li>
3333

3434
<li>
35-
<a href="https://www.bamsoftware.com/hacks/zipbomb/">A great research to gain more impact by this kind of attacks</a>
35+
<a href="https://www.bamsoftware.com/hacks/zipbomb/">An explanation of the attack</a>
3636
</li>
3737

3838
</references>
Lines changed: 6 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,15 @@
1-
#include <iostream>
2-
#include <vector>
31
#include "zlib.h"
4-
#include <cstdio>
5-
#include <cstring>
62

7-
int UnsafeInflate(int argc, char *argv[]) {
8-
// original string len = 36
9-
char a[50] = "Hello Hello Hello Hello Hello Hello!";
10-
// placeholder for the compressed (deflated) version of "a"
11-
char b[50];
12-
// placeholder for the Uncompressed (inflated) version of "b"
13-
char c[50];
14-
printf("Uncompressed size is: %lu\n", strlen(a));
15-
printf("Uncompressed string is: %s\n", a);
16-
printf("\n----------\n\n");
17-
18-
// STEP 1.
19-
// zlib struct
20-
z_stream defstream;
21-
defstream.zalloc = Z_NULL;
22-
defstream.zfree = Z_NULL;
23-
defstream.opaque = Z_NULL;
24-
// setup "a" as the input and "b" as the compressed output
25-
defstream.avail_in = (uInt) strlen(a) + 1; // size of input, string + terminator
26-
defstream.next_in = (Bytef *) a; // input char array
27-
defstream.avail_out = (uInt) sizeof(b); // size of output
28-
defstream.next_out = (Bytef *) b; // output char array
29-
30-
// the actual compression work.
31-
deflateInit(&defstream, Z_BEST_COMPRESSION);
32-
deflate(&defstream, Z_FINISH);
33-
deflateEnd(&defstream);
34-
35-
// This is one way of getting the size of the output
36-
printf("Compressed size is: %lu\n", strlen(b));
37-
printf("Compressed string is: %s\n", b);
38-
printf("\n----------\n\n");
39-
// STEP 2.
40-
// inflate b into c
41-
// zlib struct
42-
z_stream infstream;
43-
infstream.zalloc = Z_NULL;
44-
infstream.zfree = Z_NULL;
45-
infstream.opaque = Z_NULL;
46-
// setup "b" as the input and "c" as the compressed output
47-
// TOTHINK: Here we can add additional step from Right operand to z_stream variable access
48-
infstream.avail_in = (uInt) ((char *) defstream.next_out - b); // size of input
49-
infstream.next_in = (Bytef *) b; // input char array
50-
infstream.avail_out = (uInt) sizeof(c); // size of output
51-
infstream.next_out = (Bytef *) c; // output char array
52-
53-
// uLong total_out; /* total number of bytes output so far */
54-
// the actual DE-compression work.
55-
inflateInit(&infstream);
56-
std::cout << infstream.total_out << std::endl;
57-
inflate(&infstream, Z_NO_FLUSH);
58-
std::cout << infstream.total_out << std::endl;
59-
inflateEnd(&infstream);
60-
61-
printf("Uncompressed size is: %lu\n", strlen(c));
62-
printf("Uncompressed string is: %s\n", c);
63-
return 0;
64-
}
65-
66-
int UnsafeGzread() {
67-
std::cout << "enter compressed file name!\n" << std::endl;
68-
char fileName[100];
69-
std::cin >> fileName;
70-
gzFile inFileZ = gzopen(fileName, "rb");
71-
if (inFileZ == nullptr) {
72-
printf("Error: Failed to gzopen %s\n", fileName);
73-
exit(0);
74-
}
75-
unsigned char unzipBuffer[8192];
3+
void UnsafeGzread(gzFile inFileZ) {
4+
const int BUFFER_SIZE = 8192;
5+
unsigned char unzipBuffer[BUFFER_SIZE];
766
unsigned int unzippedBytes;
77-
std::vector<unsigned char> unzippedData;
787
while (true) {
79-
unzippedBytes = gzread(inFileZ, unzipBuffer, 8192);
80-
if (unzippedBytes > 0) {
81-
unzippedData.insert(unzippedData.end(), unzipBuffer, unzipBuffer + unzippedBytes);
82-
} else {
8+
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
9+
if (unzippedBytes <= 0) {
8310
break;
8411
}
85-
}
86-
for (auto &&i: unzippedData)
87-
std::cout << i;
88-
gzclose(inFileZ);
89-
return 0;
90-
}
9112

92-
int UnsafeGzfread() {
93-
std::cout << "enter compressed file name!\n" << std::endl;
94-
char fileName[100];
95-
std::cin >> fileName;
96-
gzFile inFileZ = gzopen(fileName, "rb");
97-
if (inFileZ == nullptr) {
98-
printf("Error: Failed to gzopen %s\n", fileName);
99-
exit(0);
100-
}
101-
while (true) {
102-
char buffer[1000];
103-
if (!gzfread(buffer, 999, 1, inFileZ)) {
104-
break;
105-
}
106-
}
107-
gzclose(inFileZ);
108-
return 0;
109-
}
110-
111-
int UnsafeGzgets() {
112-
std::cout << "enter compressed file name!\n" << std::endl;
113-
char fileName[100];
114-
std::cin >> fileName;
115-
gzFile inFileZ = gzopen(fileName, "rb");
116-
if (inFileZ == nullptr) {
117-
printf("Error: Failed to gzopen %s\n", fileName);
118-
exit(0);
119-
}
120-
char *buffer = new char[4000000000];
121-
char *result = gzgets(inFileZ, buffer, 1000000000);
122-
while (true) {
123-
result = gzgets(inFileZ, buffer, 1000000000);
124-
if (result == nullptr) {
125-
break;
126-
}
13+
// process buffer
12714
}
128-
return 0;
12915
}
Lines changed: 11 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,23 @@
1-
#include <iostream>
2-
#include <vector>
31
#include "zlib.h"
4-
#include <cstdio>
5-
#include <cstring>
62

7-
int SafeGzread() {
8-
std::cout << "enter compressed file name!\n" << std::endl;
9-
char fileName[100];
10-
std::cin >> fileName;
11-
gzFile inFileZ = gzopen(fileName, "rb");
12-
if (inFileZ == nullptr) {
13-
printf("Error: Failed to gzopen %s\n", fileName);
14-
exit(0);
15-
}
16-
unsigned char unzipBuffer[8192];
3+
void SafeGzread(gzFile inFileZ) {
4+
const int MAX_READ = 1024 * 1024 * 4;
5+
const int BUFFER_SIZE = 8192;
6+
unsigned char unzipBuffer[BUFFER_SIZE];
177
unsigned int unzippedBytes;
18-
uint totalRead = 0;
19-
std::vector<unsigned char> unzippedData;
8+
unsigned int totalRead = 0;
209
while (true) {
21-
unzippedBytes = gzread(inFileZ, unzipBuffer, 8192);
10+
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
2211
totalRead += unzippedBytes;
23-
if (unzippedBytes > 0) {
24-
unzippedData.insert(unzippedData.end(), unzipBuffer, unzipBuffer + unzippedBytes);
25-
if (totalRead > 1024 * 1024 * 4) {
26-
std::cout << "Bombs!" << totalRead;
27-
exit(1);
28-
} else {
29-
std::cout << "not Bomb yet!!" << totalRead << std::endl;
30-
}
31-
} else {
12+
if (unzippedBytes <= 0) {
3213
break;
3314
}
34-
}
35-
36-
for (auto &&i: unzippedData)
37-
std::cout << i;
38-
gzclose(inFileZ);
3915

40-
return 0;
41-
}
42-
43-
int SafeGzread2() {
44-
std::cout << "enter compressed file name!\n" << std::endl;
45-
char fileName[100];
46-
std::cin >> fileName;
47-
gzFile inFileZ = gzopen(fileName, "rb");
48-
if (inFileZ == nullptr) {
49-
printf("Error: Failed to gzopen %s\n", fileName);
50-
exit(0);
51-
}
52-
const int BUFFER_SIZE = 8192;
53-
unsigned char unzipBuffer[BUFFER_SIZE];
54-
unsigned int unzippedBytes;
55-
uint totalRead = 0;
56-
std::vector<unsigned char> unzippedData;
57-
while (true) {
58-
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
59-
totalRead += BUFFER_SIZE;
60-
if (unzippedBytes > 0) {
61-
unzippedData.insert(unzippedData.end(), unzipBuffer, unzipBuffer + unzippedBytes);
62-
if (totalRead > 1024 * 1024 * 4) {
63-
std::cout << "Bombs!" << totalRead;
64-
exit(1);
65-
} else {
66-
std::cout << "not Bomb yet!!" << totalRead << std::endl;
67-
}
68-
} else {
16+
if (totalRead > MAX_READ) {
17+
// Possible decompression bomb, stop processing.
6918
break;
19+
} else {
20+
// process buffer
7021
}
7122
}
72-
73-
for (auto &&i: unzippedData)
74-
std::cout << i;
75-
gzclose(inFileZ);
76-
77-
return 0;
7823
}

0 commit comments

Comments
 (0)