Skip to content

Commit 62d14db

Browse files
andrecsilvapixeebot[bot]nahsra
authored
Added new codemod to fix SQL table injections (#412)
Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com> Co-authored-by: pixeebot[bot] <pixeebot[bot]@users.noreply.github.com> Co-authored-by: Arshan Dabirsiaghi <[email protected]>
1 parent 7db059c commit 62d14db

17 files changed

+535
-35
lines changed

core-codemods/src/main/java/io/codemodder/codemods/DefectDojoSqlInjectionCodemod.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import com.github.javaparser.ast.CompilationUnit;
44
import io.codemodder.*;
5-
import io.codemodder.codemods.util.JavaParserSQLInjectionRemediatorStrategy;
65
import io.codemodder.codetf.DetectorRule;
76
import io.codemodder.javaparser.JavaParserChanger;
87
import io.codemodder.providers.defectdojo.DefectDojoScan;
98
import io.codemodder.providers.defectdojo.Finding;
109
import io.codemodder.providers.defectdojo.RuleFindings;
10+
import io.codemodder.remediation.sqlinjection.JavaParserSQLInjectionRemediatorStrategy;
1111
import java.util.List;
1212
import java.util.Objects;
1313
import javax.inject.Inject;

core-codemods/src/main/java/io/codemodder/codemods/HQLParameterizationCodemod.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.codemodder.*;
1212
import io.codemodder.ast.ASTTransforms;
1313
import io.codemodder.javaparser.JavaParserChanger;
14+
import io.codemodder.remediation.sqlinjection.QueryParameterizer;
1415
import java.util.ArrayList;
1516
import java.util.Deque;
1617
import java.util.List;

core-codemods/src/main/java/io/codemodder/codemods/SQLParameterizerCodemod.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.github.javaparser.ast.expr.MethodCallExpr;
55
import io.codemodder.*;
66
import io.codemodder.javaparser.JavaParserChanger;
7+
import io.codemodder.remediation.sqlinjection.SQLParameterizerWithCleanup;
78
import java.util.List;
89
import java.util.Optional;
910

core-codemods/src/main/java/io/codemodder/codemods/SonarSQLInjectionCodemod.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import com.github.javaparser.ast.CompilationUnit;
44
import io.codemodder.*;
5-
import io.codemodder.codemods.util.JavaParserSQLInjectionRemediatorStrategy;
65
import io.codemodder.codetf.DetectorRule;
76
import io.codemodder.providers.sonar.ProvidedSonarScan;
87
import io.codemodder.providers.sonar.RuleHotspot;
98
import io.codemodder.providers.sonar.SonarRemediatingJavaParserChanger;
109
import io.codemodder.remediation.GenericRemediationMetadata;
10+
import io.codemodder.remediation.sqlinjection.JavaParserSQLInjectionRemediatorStrategy;
1111
import io.codemodder.sonar.model.Hotspot;
1212
import io.codemodder.sonar.model.SonarFinding;
1313
import java.util.List;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.codemodder.codemods;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import java.util.regex.Pattern;
7+
import org.junit.jupiter.api.Test;
8+
9+
final class AlphanumericBlacklistFilterTest {
10+
11+
String validateTableName(final String tablename) {
12+
Pattern regex = Pattern.compile("[a-zA-Z0-9_]+(.[a-zA-Z0-9_]+)?");
13+
if (!regex.matcher(tablename).matches()) {
14+
throw new SecurityException("Supplied table name contains non-alphanumeric characters");
15+
}
16+
return tablename;
17+
}
18+
19+
@Test
20+
void it_tests_basic_alpha_string() {
21+
String tablename = "the_quick_brown_fox_jumps_over_the_lazy_dog_1234567890";
22+
assertEquals(validateTableName(tablename), tablename);
23+
}
24+
25+
@Test
26+
void it_accepts_schema_table_name() {
27+
String tablename = "schema.table";
28+
assertEquals(validateTableName(tablename), tablename);
29+
}
30+
31+
@Test
32+
void it_rejects_non_alphanumeric() {
33+
String tablename = "\"reject_this\" where 1=1";
34+
SecurityException e = assertThrows(SecurityException.class, () -> validateTableName(tablename));
35+
assertEquals("Supplied table name contains non-alphanumeric characters", e.getMessage());
36+
}
37+
}

core-codemods/src/test/java/io/codemodder/codemods/SonarSQLInjectionCodemodTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,13 @@ class UnsupportedTest implements CodemodTestMixin {}
2424
expectingFixesAtLines = {69},
2525
dependencies = {})
2626
class SupportedTest implements CodemodTestMixin {}
27+
28+
@Nested
29+
@Metadata(
30+
codemodType = SonarSQLInjectionCodemod.class,
31+
testResourceDir = "sonar-sql-injection-s2077/supportedTableInjection",
32+
renameTestFile = "core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
33+
expectingFixesAtLines = {19, 25, 33, 40},
34+
dependencies = {})
35+
class SupportedTableInjectionTest implements CodemodTestMixin {}
2736
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.acme.testcode;
2+
3+
import java.sql.Connection;
4+
import java.sql.ResultSet;
5+
import java.sql.SQLException;
6+
import java.sql.Statement;
7+
import java.sql.PreparedStatement;
8+
import java.util.Scanner;
9+
import java.util.regex.Pattern;
10+
11+
public final class SQLTest {
12+
13+
private Connection conn;
14+
15+
public ResultSet simpleIndirect() throws SQLException {
16+
Scanner scanner = new Scanner(System.in);
17+
String input = scanner.nextLine();
18+
String sql = "SELECT * FROM " + validateTableName(input + "");
19+
Statement stmt = conn.createStatement();
20+
return stmt.executeQuery(sql);
21+
}
22+
23+
public boolean simplePreparedStatementDirect() throws SQLException {
24+
Scanner scanner = new Scanner(System.in);
25+
String input = scanner.nextLine();
26+
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM " + validateTableName(input + ""));
27+
return stmt.execute();
28+
}
29+
30+
public ResultSet deleteStatement() throws SQLException {
31+
Scanner scanner = new Scanner(System.in);
32+
String input = scanner.nextLine();
33+
Statement stmt = conn.createStatement();
34+
return stmt.executeQuery("DELETE FROM " + validateTableName(input + "") + " WHERE 1=1");
35+
}
36+
37+
public ResultSet withQuotes() throws SQLException {
38+
Scanner scanner = new Scanner(System.in);
39+
String input = scanner.nextLine();
40+
Statement stmt = conn.createStatement();
41+
return stmt.executeQuery("DELETE FROM \"" + validateTableName(input + "") + "\" WHERE 1=1");
42+
}
43+
44+
public ResultSet ignoreStatic() throws SQLException {
45+
Scanner scanner = new Scanner(System.in);
46+
String input = scanner.nextLine();
47+
Statement stmt = conn.createStatement();
48+
return stmt.executeQuery("SELECT * FROM " + "user_table");
49+
}
50+
51+
String validateTableName(final String tablename) {
52+
Pattern regex = Pattern.compile("[a-zA-Z0-9_]+(.[a-zA-Z0-9_]+)?");
53+
if (!regex.matcher(tablename).matches()) {
54+
throw new SecurityException("Supplied table name contains non-alphanumeric characters");
55+
}
56+
return tablename;
57+
}
58+
59+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.acme.testcode;
2+
3+
import java.sql.Connection;
4+
import java.sql.ResultSet;
5+
import java.sql.SQLException;
6+
import java.sql.Statement;
7+
import java.sql.PreparedStatement;
8+
import java.util.Scanner;
9+
10+
public final class SQLTest {
11+
12+
private Connection conn;
13+
14+
public ResultSet simpleIndirect() throws SQLException {
15+
Scanner scanner = new Scanner(System.in);
16+
String input = scanner.nextLine();
17+
String sql = "SELECT * FROM " + input;
18+
Statement stmt = conn.createStatement();
19+
return stmt.executeQuery(sql);
20+
}
21+
22+
public boolean simplePreparedStatementDirect() throws SQLException {
23+
Scanner scanner = new Scanner(System.in);
24+
String input = scanner.nextLine();
25+
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM " + input);
26+
return stmt.execute();
27+
}
28+
29+
public ResultSet deleteStatement() throws SQLException {
30+
Scanner scanner = new Scanner(System.in);
31+
String input = scanner.nextLine();
32+
Statement stmt = conn.createStatement();
33+
return stmt.executeQuery("DELETE FROM " + input + " WHERE 1=1");
34+
}
35+
36+
public ResultSet withQuotes() throws SQLException {
37+
Scanner scanner = new Scanner(System.in);
38+
String input = scanner.nextLine();
39+
Statement stmt = conn.createStatement();
40+
return stmt.executeQuery("DELETE FROM \"" + input + "\" WHERE 1=1");
41+
}
42+
43+
public ResultSet ignoreStatic() throws SQLException {
44+
Scanner scanner = new Scanner(System.in);
45+
String input = scanner.nextLine();
46+
Statement stmt = conn.createStatement();
47+
return stmt.executeQuery("SELECT * FROM " + "user_table");
48+
}
49+
50+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
{
2+
"paging": {
3+
"pageIndex": 1,
4+
"pageSize": 100,
5+
"total": 4
6+
},
7+
"hotspots": [
8+
{
9+
"key": "AZCR88Tp4FI6qXo1Oo7Z",
10+
"component": "pixee_codemodder-java:core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
11+
"project": "pixee_codemodder-java",
12+
"securityCategory": "sql-injection",
13+
"vulnerabilityProbability": "HIGH",
14+
"status": "TO_REVIEW",
15+
"line": 19,
16+
"message": "Make sure using a dynamically formatted SQL query is safe here.",
17+
"creationDate": "2024-07-08T12:45:43+0200",
18+
"updateDate": "2024-07-08T12:45:59+0200",
19+
"textRange": {
20+
"startLine": 19,
21+
"endLine": 19,
22+
"startOffset": 29,
23+
"endOffset": 32
24+
},
25+
"flows": [],
26+
"ruleKey": "java:S2077"
27+
},
28+
{
29+
"key": "AZCR9sx3sB8d7cmTiSDr",
30+
"component": "pixee_codemodder-java:core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
31+
"project": "pixee_codemodder-java",
32+
"securityCategory": "sql-injection",
33+
"vulnerabilityProbability": "HIGH",
34+
"status": "TO_REVIEW",
35+
"line": 25,
36+
"message": "Make sure using a dynamically formatted SQL query is safe here.",
37+
"creationDate": "2024-07-08T12:49:19+0200",
38+
"updateDate": "2024-07-08T12:49:19+0200",
39+
"textRange": {
40+
"startLine": 25,
41+
"endLine": 25,
42+
"startOffset": 51,
43+
"endOffset": 75
44+
},
45+
"flows": [],
46+
"ruleKey": "java:S2077"
47+
},
48+
{
49+
"key": "AZCR9sx3sB8d7cmTiSDs",
50+
"component": "pixee_codemodder-java:core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
51+
"project": "pixee_codemodder-java",
52+
"securityCategory": "sql-injection",
53+
"vulnerabilityProbability": "HIGH",
54+
"status": "TO_REVIEW",
55+
"line": 33,
56+
"message": "Make sure using a dynamically formatted SQL query is safe here.",
57+
"creationDate": "2024-07-08T12:49:19+0200",
58+
"updateDate": "2024-07-08T12:49:19+0200",
59+
"textRange": {
60+
"startLine": 33,
61+
"endLine": 33,
62+
"startOffset": 29,
63+
"endOffset": 66
64+
},
65+
"flows": [],
66+
"ruleKey": "java:S2077"
67+
},
68+
{
69+
"key": "AZCR9sx3sB8d7cmTiSDt",
70+
"component": "pixee_codemodder-java:core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
71+
"project": "pixee_codemodder-java",
72+
"securityCategory": "sql-injection",
73+
"vulnerabilityProbability": "HIGH",
74+
"status": "TO_REVIEW",
75+
"line": 40,
76+
"message": "Make sure using a dynamically formatted SQL query is safe here.",
77+
"creationDate": "2024-07-08T12:49:19+0200",
78+
"updateDate": "2024-07-08T12:49:19+0200",
79+
"textRange": {
80+
"startLine": 40,
81+
"endLine": 40,
82+
"startOffset": 29,
83+
"endOffset": 70
84+
},
85+
"flows": [],
86+
"ruleKey": "java:S2077"
87+
}
88+
],
89+
"components": [
90+
{
91+
"organization": "pixee",
92+
"key": "pixee_codemodder-java",
93+
"qualifier": "TRK",
94+
"name": "codemodder-java",
95+
"longName": "codemodder-java",
96+
"pullRequest": "412"
97+
},
98+
{
99+
"organization": "pixee",
100+
"key": "pixee_codemodder-java:core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
101+
"qualifier": "FIL",
102+
"name": "SQLTest.java",
103+
"longName": "core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
104+
"path": "core-codemods/src/main/java/io/codemodder/codemods/SQLTest.java",
105+
"pullRequest": "412"
106+
}
107+
]
108+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package io.codemodder.remediation.sqlinjection;
2+
3+
final class DefaultHQLInjectionRemediator implements HQLInjectionRemediator {}

0 commit comments

Comments
 (0)