Skip to content

Commit 2ff2d25

Browse files
committed
Java: Cherry-pick test from github#17051
1 parent 408a38d commit 2ff2d25

File tree

4 files changed

+807
-0
lines changed

4 files changed

+807
-0
lines changed
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
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.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.Collections;
14+
import java.util.HashSet;
15+
import java.util.List;
16+
import java.util.Set;
17+
import java.util.function.Consumer;
18+
19+
class AllowListSanitizerWithJavaUtilList {
20+
public static Connection connection;
21+
public static final List<String> goodAllowList1 = List.of("allowed1", "allowed2", "allowed3");
22+
public static final List<String> goodAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1"));
23+
public static final List<String> goodAllowList3;
24+
public static final List<String> goodAllowList4;
25+
public static final List<String> badAllowList1 = List.of("allowed1", "allowed2", getNonConstantString());
26+
public static final List<String> badAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString()));
27+
public static final List<String> badAllowList3;
28+
public static final List<String> badAllowList4;
29+
public static final List<String> badAllowList5;
30+
public static List<String> badAllowList6 = List.of("allowed1", "allowed2", "allowed3");
31+
public final List<String> badAllowList7 = List.of("allowed1", "allowed2", "allowed3");
32+
33+
static {
34+
goodAllowList3 = List.of("allowed1", "allowed2", "allowed3");
35+
goodAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2"));
36+
badAllowList3 = List.of(getNonConstantString(), "allowed2", "allowed3");
37+
badAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString()));
38+
badAllowList5 = new ArrayList<String>();
39+
badAllowList5.add("allowed1");
40+
badAllowList5.add("allowed2");
41+
badAllowList5.add("allowed3");
42+
}
43+
44+
public static String getNonConstantString() {
45+
return String.valueOf(System.currentTimeMillis());
46+
}
47+
48+
public static void main(String[] args) throws IOException, SQLException {
49+
badAllowList6 = List.of("allowed1", getNonConstantString(), "allowed3");
50+
testStaticFields(args);
51+
testLocal(args);
52+
var x = new AllowListSanitizerWithJavaUtilList();
53+
x.testNonStaticFields(args);
54+
testMultipleSources(args);
55+
testEscape(args);
56+
}
57+
58+
private static void testStaticFields(String[] args) throws IOException, SQLException {
59+
String tainted = args[1];
60+
// GOOD: an allowlist is used with constant strings
61+
if(goodAllowList1.contains(tainted.toLowerCase())){
62+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
63+
+ tainted + "' ORDER BY PRICE";
64+
ResultSet results = connection.createStatement().executeQuery(query);
65+
}
66+
// GOOD: an allowlist is used with constant strings
67+
if(goodAllowList2.contains(tainted.toUpperCase())){
68+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
69+
+ tainted + "' ORDER BY PRICE";
70+
ResultSet results = connection.createStatement().executeQuery(query);
71+
}
72+
// GOOD: an allowlist is used with constant strings
73+
if(goodAllowList3.contains(tainted)){
74+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
75+
+ tainted + "' ORDER BY PRICE";
76+
ResultSet results = connection.createStatement().executeQuery(query);
77+
}
78+
// GOOD: an allowlist is used with constant strings
79+
if(goodAllowList4.contains(tainted)){
80+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
81+
+ tainted + "' ORDER BY PRICE";
82+
ResultSet results = connection.createStatement().executeQuery(query);
83+
}
84+
// BAD: an allowlist is used with constant strings
85+
if(badAllowList1.contains(tainted)){
86+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
87+
+ tainted + "' ORDER BY PRICE";
88+
ResultSet results = connection.createStatement().executeQuery(query);
89+
}
90+
// BAD: an allowlist is used with constant strings
91+
if(badAllowList2.contains(tainted)){
92+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
93+
+ tainted + "' ORDER BY PRICE";
94+
ResultSet results = connection.createStatement().executeQuery(query);
95+
}
96+
// BAD: an allowlist is used with constant strings
97+
if(badAllowList3.contains(tainted)){
98+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
99+
+ tainted + "' ORDER BY PRICE";
100+
ResultSet results = connection.createStatement().executeQuery(query);
101+
}
102+
// BAD: an allowlist is used with constant strings
103+
if(badAllowList4.contains(tainted)){
104+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
105+
+ tainted + "' ORDER BY PRICE";
106+
ResultSet results = connection.createStatement().executeQuery(query);
107+
}
108+
// BAD: an allowlist is used with constant strings
109+
if(badAllowList5.contains(tainted)){
110+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
111+
+ tainted + "' ORDER BY PRICE";
112+
ResultSet results = connection.createStatement().executeQuery(query);
113+
}
114+
// BAD: the allowlist is in a non-final field
115+
if(badAllowList6.contains(tainted)){
116+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
117+
+ tainted + "' ORDER BY PRICE";
118+
ResultSet results = connection.createStatement().executeQuery(query);
119+
}
120+
}
121+
122+
private void testNonStaticFields(String[] args) throws IOException, SQLException {
123+
String tainted = args[0];
124+
// BAD: the allowlist is in a non-static field
125+
if(badAllowList7.contains(tainted)){
126+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
127+
+ tainted + "' ORDER BY PRICE";
128+
ResultSet results = connection.createStatement().executeQuery(query);
129+
}
130+
}
131+
132+
private static void testLocal(String[] args) throws IOException, SQLException {
133+
String tainted = args[1];
134+
// GOOD: an allowlist is used with constant strings
135+
{
136+
List<String> allowlist = List.of("allowed1", "allowed2", "allowed3");
137+
if(allowlist.contains(tainted.toLowerCase())){
138+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
139+
+ tainted + "' ORDER BY PRICE";
140+
ResultSet results = connection.createStatement().executeQuery(query);
141+
}
142+
}
143+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
144+
{
145+
List<String> allowlist = List.of("allowed1", "allowed2", args[2]);
146+
if(allowlist.contains(tainted)){
147+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
148+
+ tainted + "' ORDER BY PRICE";
149+
ResultSet results = connection.createStatement().executeQuery(query);
150+
}
151+
}
152+
// GOOD: an allowlist is used with constant strings
153+
{
154+
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
155+
List<String> allowlist = List.of(allowedArray);
156+
if(allowlist.contains(tainted.toUpperCase())){
157+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
158+
+ tainted + "' ORDER BY PRICE";
159+
ResultSet results = connection.createStatement().executeQuery(query);
160+
}
161+
}
162+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
163+
{
164+
String[] allowedArray = {"allowed1", "allowed2", args[2]};
165+
List<String> allowlist = List.of(allowedArray);
166+
if(allowlist.contains(tainted)){
167+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
168+
+ tainted + "' ORDER BY PRICE";
169+
ResultSet results = connection.createStatement().executeQuery(query);
170+
}
171+
}
172+
// GOOD: an allowlist is used with constant strings
173+
{
174+
List<String> allowlist = Collections.unmodifiableList(Arrays.asList("allowed1"));
175+
if(allowlist.contains(tainted)){
176+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
177+
+ tainted + "' ORDER BY PRICE";
178+
ResultSet results = connection.createStatement().executeQuery(query);
179+
}
180+
}
181+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
182+
{
183+
List<String> allowlist = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2", args[2]));
184+
if(allowlist.contains(tainted)){
185+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
186+
+ tainted + "' ORDER BY PRICE";
187+
ResultSet results = connection.createStatement().executeQuery(query);
188+
}
189+
}
190+
// GOOD: an allowlist is used with constant strings
191+
{
192+
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
193+
List<String> allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray));
194+
if(allowlist.contains(tainted)){
195+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
196+
+ tainted + "' ORDER BY PRICE";
197+
ResultSet results = connection.createStatement().executeQuery(query);
198+
}
199+
}
200+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
201+
{
202+
String[] allowedArray = {"allowed1", "allowed2", args[2]};
203+
List<String> allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray));
204+
if(allowlist.contains(tainted)){
205+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
206+
+ tainted + "' ORDER BY PRICE";
207+
ResultSet results = connection.createStatement().executeQuery(query);
208+
}
209+
}
210+
// GOOD: an allowlist is used with constant string
211+
{
212+
List<String> allowlist = new ArrayList<String>();
213+
allowlist.add("allowed1");
214+
allowlist.add("allowed2");
215+
allowlist.add("allowed3");
216+
if(allowlist.contains(tainted)){
217+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
218+
+ tainted + "' ORDER BY PRICE";
219+
ResultSet results = connection.createStatement().executeQuery(query);
220+
}
221+
}
222+
// BAD: an allowlist is used but one of the entries is not a compile-time constant
223+
{
224+
List<String> allowlist = new ArrayList<String>();
225+
allowlist.add("allowed1");
226+
allowlist.add(getNonConstantString());
227+
allowlist.add("allowed3");
228+
if(allowlist.contains(tainted)){
229+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
230+
+ tainted + "' ORDER BY PRICE";
231+
ResultSet results = connection.createStatement().executeQuery(query);
232+
}
233+
}
234+
// BAD: an allowlist is used but it contains a non-compile-time constant element
235+
{
236+
List<String> allowlist = new ArrayList<String>();
237+
allowlist.add("allowed1");
238+
addNonConstantStringDirectly(allowlist);
239+
if(allowlist.contains(tainted)){
240+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
241+
+ tainted + "' ORDER BY PRICE";
242+
ResultSet results = connection.createStatement().executeQuery(query);
243+
}
244+
}
245+
}
246+
247+
private static void testMultipleSources(String[] args) throws IOException, SQLException {
248+
String tainted = args[1];
249+
boolean b = args[2] == "True";
250+
{
251+
// BAD: an allowlist is used which might contain constant strings
252+
List<String> allowlist = new ArrayList<String>();
253+
allowlist.add("allowed1");
254+
if (b) {
255+
allowlist.add(getNonConstantString());
256+
}
257+
if(allowlist.contains(tainted)){
258+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
259+
+ tainted + "' ORDER BY PRICE";
260+
ResultSet results = connection.createStatement().executeQuery(query);
261+
}
262+
}
263+
{
264+
// BAD: an allowlist is used which might contain constant strings
265+
List<String> allowlist = b ? goodAllowList1 : badAllowList1;
266+
if(allowlist.contains(tainted)){
267+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
268+
+ tainted + "' ORDER BY PRICE";
269+
ResultSet results = connection.createStatement().executeQuery(query);
270+
}
271+
}
272+
{
273+
// BAD: an allowlist is used which might contain constant strings
274+
List<String> allowlist = b ? goodAllowList1 : List.of("allowed1", "allowed2", args[2]);;
275+
if(allowlist.contains(tainted)){
276+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
277+
+ tainted + "' ORDER BY PRICE";
278+
ResultSet results = connection.createStatement().executeQuery(query);
279+
}
280+
}
281+
}
282+
283+
private static void testEscape(String[] args) throws IOException, SQLException {
284+
String tainted = args[1];
285+
boolean b = args[2] == "True";
286+
{
287+
// BAD: an allowlist is used which contains constant strings
288+
List<String> allowlist = new ArrayList<String>();
289+
addNonConstantStringViaLambda(e -> allowlist.add(e));
290+
if(allowlist.contains(tainted)){ // missing result
291+
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
292+
+ tainted + "' ORDER BY PRICE";
293+
ResultSet results = connection.createStatement().executeQuery(query);
294+
}
295+
}
296+
}
297+
298+
private static void addNonConstantStringDirectly(List<String> list) {
299+
list.add(getNonConstantString());
300+
}
301+
302+
private static void addNonConstantStringViaLambda(Consumer<String> adder) {
303+
adder.accept(getNonConstantString());
304+
}
305+
306+
}

0 commit comments

Comments
 (0)