Skip to content

Commit a1e1cb1

Browse files
committed
Add tests for java.util.Set
1 parent d667ac2 commit a1e1cb1

File tree

4 files changed

+401
-72
lines changed

4 files changed

+401
-72
lines changed

java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizer.java renamed to java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import java.util.Collections;
1414
import java.util.List;
1515

16-
class AllowListSanitizer {
16+
class AllowListSanitizerWithJavaUtilList {
1717
public static Connection connection;
1818
public static final List<String> goodAllowList1 = List.of("allowed1", "allowed2", "allowed3");
1919
public static final List<String> goodAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1"));
@@ -46,7 +46,7 @@ public static void main(String[] args) throws IOException, SQLException {
4646
badAllowList6 = List.of("allowed1", getNonConstantString(), "allowed3");
4747
testStaticFields(args);
4848
testLocal(args);
49-
var x = new AllowListSanitizer();
49+
var x = new AllowListSanitizerWithJavaUtilList();
5050
x.testNonStaticFields(args);
5151
}
5252

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// Test cases for CWE-089 (SQL injection and Java Persistence query injection)
2+
// http://cwe.mitre.org/data/definitions/89.html
3+
package test.cwe089.semmle.tests;
4+
5+
import java.io.IOException;
6+
import java.sql.Connection;
7+
import java.sql.PreparedStatement;
8+
import java.sql.ResultSet;
9+
import java.sql.SQLException;
10+
import java.sql.Statement;
11+
import java.util.HashSet;
12+
import java.util.List;
13+
import java.util.Arrays;
14+
import java.util.Collections;
15+
import java.util.Set;
16+
17+
class AllowListSanitizerWithJavaUtilSet {
18+
public static Connection connection;
19+
public static final Set<String> goodAllowSet1 = Set.of("allowed1", "allowed2", "allowed3");
20+
public static final Set<String> goodAllowSet2 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1","allowed2")));
21+
public static final Set<String> goodAllowSet3;
22+
public static final Set<String> goodAllowSet4;
23+
public static final Set<String> badAllowSet1 = Set.of("allowed1", "allowed2", getNonConstantString());
24+
public static final Set<String> badAllowSet2 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1", getNonConstantString())));
25+
public static final Set<String> badAllowSet3;
26+
public static final Set<String> badAllowSet4;
27+
public static final Set<String> badAllowSet5;
28+
public static Set<String> badAllowSet6 = Set.of("allowed1", "allowed2", "allowed3");
29+
public final Set<String> badAllowSet7 = Set.of("allowed1", "allowed2", "allowed3");
30+
31+
static {
32+
goodAllowSet3 = Set.of("allowed1", "allowed2", "allowed3");
33+
goodAllowSet4 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1", "allowed2")));
34+
badAllowSet3 = Set.of(getNonConstantString(), "allowed2", "allowed3");
35+
badAllowSet4 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1", getNonConstantString())));
36+
badAllowSet5 = new HashSet<String>();
37+
badAllowSet5.add("allowed1");
38+
badAllowSet5.add("allowed2");
39+
badAllowSet5.add("allowed3");
40+
}
41+
42+
public static String getNonConstantString() {
43+
return String.valueOf(System.currentTimeMillis());
44+
}
45+
46+
public static void main(String[] args) throws IOException, SQLException {
47+
badAllowSet6 = Set.of("allowed1", getNonConstantString(), "allowed3");
48+
testStaticFields(args);
49+
testLocal(args);
50+
var x = new AllowListSanitizerWithJavaUtilSet();
51+
x.testNonStaticFields(args);
52+
}
53+
54+
private static void testStaticFields(String[] args) throws IOException, SQLException {
55+
String tainted = args[1];
56+
// GOOD: an allowSet is used with constant strings
57+
if(goodAllowSet1.contains(tainted)){
58+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
59+
+ tainted + "' ORDER BY PRICE";
60+
ResultSet results = connection.createStatement().executeQuery(query);
61+
}
62+
// GOOD: an allowSet is used with constant strings
63+
if(goodAllowSet2.contains(tainted)){
64+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
65+
+ tainted + "' ORDER BY PRICE";
66+
ResultSet results = connection.createStatement().executeQuery(query);
67+
}
68+
// GOOD: an allowSet is used with constant strings
69+
if(goodAllowSet3.contains(tainted)){
70+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
71+
+ tainted + "' ORDER BY PRICE";
72+
ResultSet results = connection.createStatement().executeQuery(query);
73+
}
74+
// GOOD: an allowSet is used with constant strings
75+
if(goodAllowSet4.contains(tainted)){
76+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
77+
+ tainted + "' ORDER BY PRICE";
78+
ResultSet results = connection.createStatement().executeQuery(query);
79+
}
80+
// BAD: an allowSet is used with constant strings
81+
if(badAllowSet1.contains(tainted)){
82+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
83+
+ tainted + "' ORDER BY PRICE";
84+
ResultSet results = connection.createStatement().executeQuery(query);
85+
}
86+
// BAD: an allowSet is used with constant strings
87+
if(badAllowSet2.contains(tainted)){
88+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
89+
+ tainted + "' ORDER BY PRICE";
90+
ResultSet results = connection.createStatement().executeQuery(query);
91+
}
92+
// BAD: an allowSet is used with constant strings
93+
if(badAllowSet3.contains(tainted)){
94+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
95+
+ tainted + "' ORDER BY PRICE";
96+
ResultSet results = connection.createStatement().executeQuery(query);
97+
}
98+
// BAD: an allowSet is used with constant strings
99+
if(badAllowSet4.contains(tainted)){
100+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
101+
+ tainted + "' ORDER BY PRICE";
102+
ResultSet results = connection.createStatement().executeQuery(query);
103+
}
104+
// BAD: an allowSet is used with constant strings
105+
if(badAllowSet5.contains(tainted)){
106+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
107+
+ tainted + "' ORDER BY PRICE";
108+
ResultSet results = connection.createStatement().executeQuery(query);
109+
}
110+
// BAD: the allowSet is in a non-final field
111+
if(badAllowSet6.contains(tainted)){
112+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
113+
+ tainted + "' ORDER BY PRICE";
114+
ResultSet results = connection.createStatement().executeQuery(query);
115+
}
116+
}
117+
118+
private void testNonStaticFields(String[] args) throws IOException, SQLException {
119+
String tainted = args[0];
120+
// BAD: the allowSet is in a non-static field
121+
if(badAllowSet7.contains(tainted)){
122+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
123+
+ tainted + "' ORDER BY PRICE";
124+
ResultSet results = connection.createStatement().executeQuery(query);
125+
}
126+
}
127+
128+
private static void testLocal(String[] args) throws IOException, SQLException {
129+
String tainted = args[1];
130+
// GOOD: an allowSet is used with constant strings
131+
{
132+
Set<String> allowSet = Set.of("allowed1", "allowed2", "allowed3");
133+
if(allowSet.contains(tainted)){
134+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
135+
+ tainted + "' ORDER BY PRICE";
136+
ResultSet results = connection.createStatement().executeQuery(query);
137+
}
138+
}
139+
// BAD: an allowSet is used but one of the entries is not a compile-time constant
140+
{
141+
Set<String> allowSet = Set.of("allowed1", "allowed2", args[2]);
142+
if(allowSet.contains(tainted)){
143+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
144+
+ tainted + "' ORDER BY PRICE";
145+
ResultSet results = connection.createStatement().executeQuery(query);
146+
}
147+
}
148+
// GOOD: an allowSet is used with constant strings
149+
{
150+
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
151+
Set<String> allowSet = Set.of(allowedArray);
152+
if(allowSet.contains(tainted)){
153+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
154+
+ tainted + "' ORDER BY PRICE";
155+
ResultSet results = connection.createStatement().executeQuery(query);
156+
}
157+
}
158+
// BAD: an allowSet is used but one of the entries is not a compile-time constant
159+
{
160+
String[] allowedArray = {"allowed1", "allowed2", args[2]};
161+
Set<String> allowSet = Set.of(allowedArray);
162+
if(allowSet.contains(tainted)){
163+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
164+
+ tainted + "' ORDER BY PRICE";
165+
ResultSet results = connection.createStatement().executeQuery(query);
166+
}
167+
}
168+
// GOOD: an allowlist is used with constant strings
169+
{
170+
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1")));
171+
if(allowlist.contains(tainted)){
172+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
173+
+ tainted + "' ORDER BY PRICE";
174+
ResultSet results = connection.createStatement().executeQuery(query);
175+
}
176+
}
177+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
178+
{
179+
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1", "allowed2", args[2])));
180+
if(allowlist.contains(tainted)){
181+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
182+
+ tainted + "' ORDER BY PRICE";
183+
ResultSet results = connection.createStatement().executeQuery(query);
184+
}
185+
}
186+
// GOOD: an allowlist is used with constant strings
187+
{
188+
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
189+
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray)));
190+
if(allowlist.contains(tainted)){
191+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
192+
+ tainted + "' ORDER BY PRICE";
193+
ResultSet results = connection.createStatement().executeQuery(query);
194+
}
195+
}
196+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
197+
{
198+
String[] allowedArray = {"allowed1", "allowed2", args[2]};
199+
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray)));
200+
if(allowlist.contains(tainted)){
201+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
202+
+ tainted + "' ORDER BY PRICE";
203+
ResultSet results = connection.createStatement().executeQuery(query);
204+
}
205+
}
206+
// GOOD: an allowSet is used with constant string
207+
{
208+
Set<String> allowSet = new HashSet<String>();
209+
allowSet.add("allowed1");
210+
allowSet.add("allowed2");
211+
allowSet.add("allowed3");
212+
if(allowSet.contains(tainted)){
213+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
214+
+ tainted + "' ORDER BY PRICE";
215+
ResultSet results = connection.createStatement().executeQuery(query);
216+
}
217+
}
218+
// BAD: an allowSet is used but one of the entries is not a compile-time constant
219+
{
220+
Set<String> allowSet = new HashSet<String>();
221+
allowSet.add("allowed1");
222+
allowSet.add(getNonConstantString());
223+
allowSet.add("allowed3");
224+
if(allowSet.contains(tainted)){
225+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
226+
+ tainted + "' ORDER BY PRICE";
227+
ResultSet results = connection.createStatement().executeQuery(query);
228+
}
229+
}
230+
}
231+
232+
}

0 commit comments

Comments
 (0)