18
18
*/
19
19
package org .apache .fineract .infrastructure .security .utils ;
20
20
21
+ import java .util .List ;
21
22
import java .util .StringTokenizer ;
22
23
import java .util .regex .Matcher ;
23
24
import java .util .regex .Pattern ;
@@ -37,23 +38,32 @@ private SQLInjectionValidator() {
37
38
38
39
private static final String SQL_PATTERN = "[a-zA-Z_=,\\ -'!><.?\" `% ()0-9*\n \r ]*" ;
39
40
41
+ // TODO: see here https://rails-sqli.org for and
42
+ // https://larrysteinle.com/2011/02/20/use-regular-expressions-to-detect-sql-code-injection more examples
43
+ private static final List <String > INJECTION_PATTERNS = List .of ("(?i).*[or|and]\s *[\" ']?-1[\" ']?\\ s*(-*).*" ,
44
+ "(?i).*\\ s+[\" ']?(\\ d+)[\" ']?\\ s*=\\ s*[\" ']?(\\ 1)[\" ']?\\ s*(-*).*" );
45
+
40
46
public static void validateSQLInput (final String sqlSearch ) {
41
47
if (StringUtils .isBlank (sqlSearch )) {
42
48
return ;
43
49
}
50
+
51
+ // TODO: this should be replaced by INJECTION_PATTERNS
44
52
String lowerCaseSQL = sqlSearch .toLowerCase ();
45
53
for (String ddl : DDL_COMMANDS ) {
46
54
if (lowerCaseSQL .contains (ddl )) {
47
55
throw new SQLInjectionException ();
48
56
}
49
57
}
50
58
59
+ // TODO: this should be replaced by INJECTION_PATTERNS
51
60
for (String dml : DML_COMMANDS ) {
52
61
if (lowerCaseSQL .contains (dml )) {
53
62
throw new SQLInjectionException ();
54
63
}
55
64
}
56
65
66
+ // TODO: this should be replaced by INJECTION_PATTERNS
57
67
for (String comments : COMMENTS ) {
58
68
if (lowerCaseSQL .contains (comments )) {
59
69
throw new SQLInjectionException ();
@@ -63,17 +73,10 @@ public static void validateSQLInput(final String sqlSearch) {
63
73
// Removing the space before and after '=' operator
64
74
// String s = " \" OR 1 = 1"; For the cases like this
65
75
boolean injectionFound = false ;
66
- String inputSqlString = lowerCaseSQL ;
67
- while (inputSqlString .indexOf (" =" ) > 0 ) { // Don't remove space before
68
- // = operator
69
- inputSqlString = inputSqlString .replaceAll (" =" , "=" );
70
- }
71
76
72
- while (inputSqlString .indexOf ("= " ) > 0 ) { // Don't remove space after =
73
- // operator
74
- inputSqlString = inputSqlString .replaceAll ("= " , "=" );
75
- }
77
+ String inputSqlString = lowerCaseSQL .replaceAll ("\\ s*=\\ s*" , "=" );
76
78
79
+ // TODO: this should be replaced by INJECTION_PATTERNS
77
80
StringTokenizer tokenizer = new StringTokenizer (inputSqlString , " " );
78
81
while (tokenizer .hasMoreTokens ()) {
79
82
String token = tokenizer .nextToken ().trim ();
@@ -118,6 +121,14 @@ public static void validateSQLInput(final String sqlSearch) {
118
121
throw new SQLInjectionException ();
119
122
}
120
123
124
+ for (String injectionPattern : INJECTION_PATTERNS ) {
125
+ Pattern pattern = Pattern .compile (injectionPattern );
126
+ Matcher matcher = pattern .matcher (sqlSearch );
127
+ if (matcher .matches ()) {
128
+ throw new SQLInjectionException ();
129
+ }
130
+ }
131
+
121
132
Pattern pattern = Pattern .compile (SQL_PATTERN );
122
133
Matcher matcher = pattern .matcher (sqlSearch );
123
134
if (!matcher .matches ()) {
@@ -129,13 +140,16 @@ public static void validateAdhocQuery(final String sqlSearch) {
129
140
if (StringUtils .isBlank (sqlSearch )) {
130
141
return ;
131
142
}
143
+
144
+ // TODO: this should be replaced by INJECTION_PATTERNS
132
145
String lowerCaseSQL = sqlSearch .toLowerCase ().trim ();
133
146
for (String ddl : DDL_COMMANDS ) {
134
147
if (lowerCaseSQL .startsWith (ddl )) {
135
148
throw new SQLInjectionException ();
136
149
}
137
150
}
138
151
152
+ // TODO: this should be replaced by INJECTION_PATTERNS
139
153
for (String comments : COMMENTS ) {
140
154
if (lowerCaseSQL .contains (comments )) {
141
155
throw new SQLInjectionException ();
@@ -145,16 +159,8 @@ public static void validateAdhocQuery(final String sqlSearch) {
145
159
// Removing the space before and after '=' operator
146
160
// String s = " \" OR 1 = 1"; For the cases like this
147
161
boolean injectionFound = false ;
148
- String inputSqlString = lowerCaseSQL ;
149
- while (inputSqlString .indexOf (" =" ) > 0 ) { // Don't remove space before
150
- // = operator
151
- inputSqlString = inputSqlString .replaceAll (" =" , "=" );
152
- }
153
162
154
- while (inputSqlString .indexOf ("= " ) > 0 ) { // Don't remove space after =
155
- // operator
156
- inputSqlString = inputSqlString .replaceAll ("= " , "=" );
157
- }
163
+ String inputSqlString = lowerCaseSQL .replaceAll ("\\ s*=\\ s*" , "=" );
158
164
159
165
StringTokenizer tokenizer = new StringTokenizer (inputSqlString , " " );
160
166
while (tokenizer .hasMoreTokens ()) {
@@ -200,6 +206,14 @@ public static void validateAdhocQuery(final String sqlSearch) {
200
206
throw new SQLInjectionException ();
201
207
}
202
208
209
+ for (String injectionPattern : INJECTION_PATTERNS ) {
210
+ Pattern pattern = Pattern .compile (injectionPattern );
211
+ Matcher matcher = pattern .matcher (sqlSearch );
212
+ if (matcher .matches ()) {
213
+ throw new SQLInjectionException ();
214
+ }
215
+ }
216
+
203
217
Pattern pattern = Pattern .compile (SQL_PATTERN );
204
218
Matcher matcher = pattern .matcher (sqlSearch );
205
219
if (!matcher .matches ()) {
0 commit comments