Skip to content

Commit 7354db8

Browse files
committed
V1 Bombs
1 parent 798f388 commit 7354db8

17 files changed

Lines changed: 1346 additions & 1 deletion

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @name Unsafe file write from a remotely provided path.
3+
* @description using apache commons upload file write sink is dangerous without sanitization
4+
* @kind path-problem
5+
* @problem.severity error
6+
* @precision high
7+
* @id java/unsafe-file-write
8+
* @tags security
9+
* experimental
10+
*/
11+
12+
import semmle.code.java.dataflow.DataFlow
13+
import semmle.code.java.dataflow.FlowSources
14+
import RemoteSource
15+
16+
module ApacheCommonsUploadFileConfig implements DataFlow::ConfigSig {
17+
predicate isSource(DataFlow::Node source) { source instanceof FormRemoteFlowSource }
18+
19+
predicate isSink(DataFlow::Node sink) {
20+
sink.asExpr() = any(ApacheCommonsFileUpload::DangerousSink::FileWriteSink s).getAPathArgument()
21+
}
22+
}
23+
24+
module BombsFlow = TaintTracking::Global<ApacheCommonsUploadFileConfig>;
25+
26+
import BombsFlow::PathGraph
27+
28+
from BombsFlow::PathNode source, BombsFlow::PathNode sink
29+
where BombsFlow::flowPath(source, sink)
30+
select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(),
31+
"potentially untrusted source"
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import java
2+
import semmle.code.java.dataflow.DataFlow
3+
4+
abstract class CLIFlowSource extends DataFlow::Node { }
5+
6+
Field childFiled(RefType rt) {
7+
not result.getType() instanceof PrimitiveType and
8+
not result.getType() instanceof BoxedType and
9+
(
10+
result.getDeclaringType() = rt or
11+
result.getDeclaringType() = childFiled(result.getDeclaringType()).getType()
12+
)
13+
}
14+
15+
module CommonsCLI {
16+
class TypeCommandLine extends RefType {
17+
TypeCommandLine() {
18+
this.getAStrictAncestor*().hasQualifiedName("org.apache.commons.cli", "CommandLine")
19+
}
20+
}
21+
22+
class TypeOption extends RefType {
23+
TypeOption() { this.getAStrictAncestor*().hasQualifiedName("org.apache.commons.cli", "Option") }
24+
}
25+
26+
class OptionValue extends CLIFlowSource {
27+
OptionValue() {
28+
exists(MethodAccess ma |
29+
ma.getCallee().getDeclaringType() instanceof TypeOption and
30+
ma.getCallee().hasName(["getValue", "getValues", "getValuesList"]) and
31+
this.asExpr() = ma
32+
)
33+
}
34+
}
35+
36+
class CommandLine extends CLIFlowSource {
37+
CommandLine() {
38+
exists(MethodAccess ma |
39+
ma.getCallee().getDeclaringType() instanceof TypeCommandLine and
40+
ma.getCallee()
41+
.hasName(["getArgs", "getArgList", "getOptionValue", "getOptionValues", "getArgs"]) and
42+
this.asExpr() = ma
43+
)
44+
}
45+
}
46+
}
47+
48+
module Args4j {
49+
class TypeCmdLineParser extends RefType {
50+
TypeCmdLineParser() {
51+
// classes of ArgumentParser interface like `SubParser`
52+
this.getAStrictAncestor*().hasQualifiedName("org.kohsuke.args4j", "CmdLineParser")
53+
}
54+
}
55+
56+
class CommandLine extends CLIFlowSource {
57+
CommandLine() {
58+
exists(Call c, ClassInstanceExpr cie, Field f |
59+
c.getCallee().getDeclaringType() instanceof TypeCmdLineParser and
60+
DataFlow::localExprFlow(cie, c.getArgument(0)) and
61+
f.getDeclaringType() = cie.getType() and
62+
(
63+
this.asExpr() = f.getAnAccess()
64+
or
65+
this.asExpr() = childFiled(f.getType()).getAnAccess()
66+
)
67+
)
68+
}
69+
}
70+
}
71+
72+
module Jcommander {
73+
class TypeBuilder extends RefType {
74+
TypeBuilder() {
75+
// classes of ArgumentParser interface like `SubParser`
76+
this.getAStrictAncestor*().hasQualifiedName("com.beust.jcommander", "JCommander$Builder")
77+
}
78+
}
79+
80+
class CommandLine extends CLIFlowSource {
81+
CommandLine() {
82+
exists(Call c, ClassInstanceExpr cie, Field f |
83+
c.getCallee().getDeclaringType() instanceof TypeBuilder and
84+
DataFlow::localExprFlow(cie, c.getArgument(0)) and
85+
f.getDeclaringType() = cie.getType() and
86+
(
87+
this.asExpr() = f.getAnAccess()
88+
or
89+
this.asExpr() = childFiled(f.getType()).getAnAccess()
90+
)
91+
)
92+
}
93+
}
94+
}
95+
96+
module Picocli {
97+
class TypeCommandLine extends RefType {
98+
TypeCommandLine() {
99+
// classes of ArgumentParser interface like `SubParser`
100+
this.getAStrictAncestor*().hasQualifiedName("picocli", "CommandLine")
101+
}
102+
}
103+
104+
class GetCallResult extends CLIFlowSource {
105+
GetCallResult() {
106+
exists(MethodAccess ma |
107+
ma.getCallee().getDeclaringType() instanceof TypeCommandLine and
108+
ma.getCallee().hasName("getExecutionResult") and
109+
this.asExpr() = ma
110+
)
111+
}
112+
}
113+
114+
class Execute extends CLIFlowSource {
115+
Execute() {
116+
exists(MethodAccess ma, ClassInstanceExpr cie, Field f |
117+
ma.getCallee().getDeclaringType() instanceof TypeCommandLine and
118+
ma.getCallee().hasName("populateCommand") and
119+
DataFlow::localExprFlow(cie, ma.getArgument(0)) and
120+
f.getDeclaringType() = cie.getType() and
121+
(
122+
this.asExpr() = f.getAnAccess()
123+
or
124+
this.asExpr() = childFiled(f.getType()).getAnAccess()
125+
)
126+
)
127+
}
128+
}
129+
130+
class CommandLine extends CLIFlowSource {
131+
CommandLine() {
132+
exists(Call c, ClassInstanceExpr cie, Field f |
133+
c.getCallee().getDeclaringType() instanceof TypeCommandLine and
134+
DataFlow::localExprFlow(cie, c.getArgument(0)) and
135+
f.getDeclaringType() = cie.getType() and
136+
(
137+
this.asExpr() = f.getAnAccess()
138+
or
139+
this.asExpr() = childFiled(f.getType()).getAnAccess()
140+
)
141+
)
142+
}
143+
}
144+
}
145+
146+
module ArgParse4j {
147+
class TypeArgumentParser extends RefType {
148+
TypeArgumentParser() {
149+
// classes of ArgumentParser interface like `SubParser`
150+
this.getAStrictAncestor*()
151+
.hasQualifiedName("net.sourceforge.argparse4j.inf", "ArgumentParser")
152+
}
153+
}
154+
155+
class TypeNamespace extends RefType {
156+
TypeNamespace() {
157+
this.getAStrictAncestor*().hasQualifiedName("net.sourceforge.argparse4j.inf", "Namespace")
158+
}
159+
}
160+
161+
class ParseArgsReturnValue extends CLIFlowSource {
162+
ParseArgsReturnValue() {
163+
exists(MethodAccess ma |
164+
ma.getReceiverType() instanceof TypeNamespace and
165+
ma.getCallee().hasName(["getString", "getList", "toString", "getByte", "get", "getAttrs"]) and
166+
this.asExpr() = ma
167+
)
168+
}
169+
}
170+
171+
class ParseArgsSecondArg extends CLIFlowSource {
172+
ParseArgsSecondArg() {
173+
exists(MethodAccess ma, ClassInstanceExpr cie, Field f |
174+
ma.getReceiverType() instanceof TypeArgumentParser and
175+
ma.getCallee().hasName(["parseArgs"]) and
176+
ma.getNumArgument() = 2 and
177+
DataFlow::localExprFlow(cie, ma.getArgument(1)) and
178+
f.getDeclaringType() = cie.getType() and
179+
(
180+
this.asExpr() = f.getAnAccess()
181+
or
182+
this.asExpr() = childFiled(f.getType()).getAnAccess()
183+
)
184+
)
185+
}
186+
}
187+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<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>
8+
9+
</overview>
10+
<recommendation>
11+
12+
<p>When you want to decompress a user-provided compressed file you must be careful about the decompression ratio or read these files within a loop byte by byte to be able to manage the decompressed size in each cycle of the loop.</p>
13+
14+
</recommendation>
15+
<example>
16+
17+
<p>
18+
Reading uncompressed ZipFile within a loop and check for a Threshold size in each cycle.
19+
</p>
20+
<sample src="example_good.java"/>
21+
22+
<p>
23+
An Unsafe Approach can be this example which we don't check for uncompressed size.
24+
</p>
25+
<sample src="example_bad.java" />
26+
27+
</example>
28+
<references>
29+
30+
<li>
31+
<a href="https://github.com/advisories/GHSA-47vx-fqr5-j2gw">CVE-2022-4565</a>
32+
</li>
33+
<li>
34+
<a href="https://www.bamsoftware.com/hacks/zipbomb/">A great research to gain more impact by this kind of attacks</a>
35+
</li>
36+
37+
</references>
38+
</qhelp>

0 commit comments

Comments
 (0)