1818 */
1919package org .apache .fineract .infrastructure .security .utils ;
2020
21+ import java .util .List ;
2122import java .util .StringTokenizer ;
2223import java .util .regex .Matcher ;
2324import java .util .regex .Pattern ;
@@ -37,10 +38,15 @@ private SQLInjectionValidator() {
3738
3839 private static final String SQL_PATTERN = "[a-zA-Z_=,\\ -'!><.?\" `% ()0-9*\n \r ]*" ;
3940
41+ // https://larrysteinle.com/2011/02/20/use-regular-expressions-to-detect-sql-code-injection more examples
42+ private static final List <String > INJECTION_PATTERNS = List .of ("(?i).*[or|and]\s *[\" ']?-1[\" ']?\\ s*(-*).*" ,
43+ "(?i).*\\ s+[\" ']?(\\ d+)[\" ']?\\ s*=\\ s*[\" ']?(\\ 1)[\" ']?\\ s*(-*).*" );
44+
4045 public static void validateSQLInput (final String sqlSearch ) {
4146 if (StringUtils .isBlank (sqlSearch )) {
4247 return ;
4348 }
49+
4450 String lowerCaseSQL = sqlSearch .toLowerCase ();
4551 for (String ddl : DDL_COMMANDS ) {
4652 if (lowerCaseSQL .contains (ddl )) {
@@ -63,16 +69,8 @@ public static void validateSQLInput(final String sqlSearch) {
6369 // Removing the space before and after '=' operator
6470 // String s = " \" OR 1 = 1"; For the cases like this
6571 boolean injectionFound = false ;
66- String inputSqlString = lowerCaseSQL ;
67- while (inputSqlString .indexOf (" =" ) > 0 ) { // Don't remove space before
68- // = operator
69- inputSqlString = inputSqlString .replaceAll (" =" , "=" );
70- }
7172
72- while (inputSqlString .indexOf ("= " ) > 0 ) { // Don't remove space after =
73- // operator
74- inputSqlString = inputSqlString .replaceAll ("= " , "=" );
75- }
73+ String inputSqlString = lowerCaseSQL .replaceAll ("\\ s*=\\ s*" , "=" );
7674
7775 StringTokenizer tokenizer = new StringTokenizer (inputSqlString , " " );
7876 while (tokenizer .hasMoreTokens ()) {
@@ -118,6 +116,14 @@ public static void validateSQLInput(final String sqlSearch) {
118116 throw new SQLInjectionException ();
119117 }
120118
119+ for (String injectionPattern : INJECTION_PATTERNS ) {
120+ Pattern pattern = Pattern .compile (injectionPattern );
121+ Matcher matcher = pattern .matcher (sqlSearch );
122+ if (matcher .matches ()) {
123+ throw new SQLInjectionException ();
124+ }
125+ }
126+
121127 Pattern pattern = Pattern .compile (SQL_PATTERN );
122128 Matcher matcher = pattern .matcher (sqlSearch );
123129 if (!matcher .matches ()) {
@@ -145,16 +151,8 @@ public static void validateAdhocQuery(final String sqlSearch) {
145151 // Removing the space before and after '=' operator
146152 // String s = " \" OR 1 = 1"; For the cases like this
147153 boolean injectionFound = false ;
148- String inputSqlString = lowerCaseSQL ;
149- while (inputSqlString .indexOf (" =" ) > 0 ) { // Don't remove space before
150- // = operator
151- inputSqlString = inputSqlString .replaceAll (" =" , "=" );
152- }
153154
154- while (inputSqlString .indexOf ("= " ) > 0 ) { // Don't remove space after =
155- // operator
156- inputSqlString = inputSqlString .replaceAll ("= " , "=" );
157- }
155+ String inputSqlString = lowerCaseSQL .replaceAll ("\\ s*=\\ s*" , "=" );
158156
159157 StringTokenizer tokenizer = new StringTokenizer (inputSqlString , " " );
160158 while (tokenizer .hasMoreTokens ()) {
@@ -200,6 +198,14 @@ public static void validateAdhocQuery(final String sqlSearch) {
200198 throw new SQLInjectionException ();
201199 }
202200
201+ for (String injectionPattern : INJECTION_PATTERNS ) {
202+ Pattern pattern = Pattern .compile (injectionPattern );
203+ Matcher matcher = pattern .matcher (sqlSearch );
204+ if (matcher .matches ()) {
205+ throw new SQLInjectionException ();
206+ }
207+ }
208+
203209 Pattern pattern = Pattern .compile (SQL_PATTERN );
204210 Matcher matcher = pattern .matcher (sqlSearch );
205211 if (!matcher .matches ()) {
0 commit comments