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,23 +38,32 @@ private SQLInjectionValidator() {
3738
3839 private static final String SQL_PATTERN = "[a-zA-Z_=,\\ -'!><.?\" `% ()0-9*\n \r ]*" ;
3940
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+
4046 public static void validateSQLInput (final String sqlSearch ) {
4147 if (StringUtils .isBlank (sqlSearch )) {
4248 return ;
4349 }
50+
51+ // TODO: this should be replaced by INJECTION_PATTERNS
4452 String lowerCaseSQL = sqlSearch .toLowerCase ();
4553 for (String ddl : DDL_COMMANDS ) {
4654 if (lowerCaseSQL .contains (ddl )) {
4755 throw new SQLInjectionException ();
4856 }
4957 }
5058
59+ // TODO: this should be replaced by INJECTION_PATTERNS
5160 for (String dml : DML_COMMANDS ) {
5261 if (lowerCaseSQL .contains (dml )) {
5362 throw new SQLInjectionException ();
5463 }
5564 }
5665
66+ // TODO: this should be replaced by INJECTION_PATTERNS
5767 for (String comments : COMMENTS ) {
5868 if (lowerCaseSQL .contains (comments )) {
5969 throw new SQLInjectionException ();
@@ -63,17 +73,10 @@ public static void validateSQLInput(final String sqlSearch) {
6373 // Removing the space before and after '=' operator
6474 // String s = " \" OR 1 = 1"; For the cases like this
6575 boolean injectionFound = false ;
66- String inputSqlString = lowerCaseSQL ;
67- while (inputSqlString .indexOf (" =" ) > 0 ) { // Don't remove space before
68- // = operator
69- inputSqlString = inputSqlString .replaceAll (" =" , "=" );
70- }
7176
72- while (inputSqlString .indexOf ("= " ) > 0 ) { // Don't remove space after =
73- // operator
74- inputSqlString = inputSqlString .replaceAll ("= " , "=" );
75- }
77+ String inputSqlString = lowerCaseSQL .replaceAll ("\\ s*=\\ s*" , "=" );
7678
79+ // TODO: this should be replaced by INJECTION_PATTERNS
7780 StringTokenizer tokenizer = new StringTokenizer (inputSqlString , " " );
7881 while (tokenizer .hasMoreTokens ()) {
7982 String token = tokenizer .nextToken ().trim ();
@@ -118,6 +121,14 @@ public static void validateSQLInput(final String sqlSearch) {
118121 throw new SQLInjectionException ();
119122 }
120123
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+
121132 Pattern pattern = Pattern .compile (SQL_PATTERN );
122133 Matcher matcher = pattern .matcher (sqlSearch );
123134 if (!matcher .matches ()) {
@@ -129,13 +140,16 @@ public static void validateAdhocQuery(final String sqlSearch) {
129140 if (StringUtils .isBlank (sqlSearch )) {
130141 return ;
131142 }
143+
144+ // TODO: this should be replaced by INJECTION_PATTERNS
132145 String lowerCaseSQL = sqlSearch .toLowerCase ().trim ();
133146 for (String ddl : DDL_COMMANDS ) {
134147 if (lowerCaseSQL .startsWith (ddl )) {
135148 throw new SQLInjectionException ();
136149 }
137150 }
138151
152+ // TODO: this should be replaced by INJECTION_PATTERNS
139153 for (String comments : COMMENTS ) {
140154 if (lowerCaseSQL .contains (comments )) {
141155 throw new SQLInjectionException ();
@@ -145,16 +159,8 @@ public static void validateAdhocQuery(final String sqlSearch) {
145159 // Removing the space before and after '=' operator
146160 // String s = " \" OR 1 = 1"; For the cases like this
147161 boolean injectionFound = false ;
148- String inputSqlString = lowerCaseSQL ;
149- while (inputSqlString .indexOf (" =" ) > 0 ) { // Don't remove space before
150- // = operator
151- inputSqlString = inputSqlString .replaceAll (" =" , "=" );
152- }
153162
154- while (inputSqlString .indexOf ("= " ) > 0 ) { // Don't remove space after =
155- // operator
156- inputSqlString = inputSqlString .replaceAll ("= " , "=" );
157- }
163+ String inputSqlString = lowerCaseSQL .replaceAll ("\\ s*=\\ s*" , "=" );
158164
159165 StringTokenizer tokenizer = new StringTokenizer (inputSqlString , " " );
160166 while (tokenizer .hasMoreTokens ()) {
@@ -200,6 +206,14 @@ public static void validateAdhocQuery(final String sqlSearch) {
200206 throw new SQLInjectionException ();
201207 }
202208
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+
203217 Pattern pattern = Pattern .compile (SQL_PATTERN );
204218 Matcher matcher = pattern .matcher (sqlSearch );
205219 if (!matcher .matches ()) {
0 commit comments