diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java b/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java index 0b3c8ed6a9..d90da8a0a2 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java +++ b/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java @@ -1,6 +1,7 @@ package com.alibaba.druid.filter.wall; import java.sql.SQLException; +import java.util.List; import java.util.Properties; import com.alibaba.druid.DruidRuntimeException; @@ -20,18 +21,19 @@ import com.alibaba.druid.util.JdbcUtils; public class WallFilter extends FilterAdapter { - private final static Log LOG = LogFactory.getLog(WallFilter.class); + private final static Log LOG = LogFactory.getLog(WallFilter.class); - private boolean inited = false; + private boolean inited = false; private WallProvider provider; - private boolean logViolation = false; - private String dbType; private WallConfig config; + private boolean logViolation = false; + private boolean throwException = true; + @Override public void init(DataSourceProxy dataSource) { this.dataSource = dataSource; @@ -77,6 +79,14 @@ public class WallFilter extends FilterAdapter { this.logViolation = logViolation; } + public boolean isThrowException() { + return throwException; + } + + public void setThrowException(boolean throwException) { + this.throwException = throwException; + } + public WallProvider getProvider() { return provider; } @@ -232,13 +242,16 @@ public class WallFilter extends FilterAdapter { } public void check(ConnectionProxy connection, String sql) throws SQLException { - try { - provider.check(sql, true); - } catch (WallRuntimeException e) { + List violations = provider.check(sql); + + if (violations.size() > 0) { if (isLogViolation()) { - LOG.error("sql injection violation : " + sql, e); + LOG.error("sql injection violation : " + sql); + } + + if (throwException) { + throw new SQLException("sql injection violation : " + sql); } - throw e; } } diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java b/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java index b5123aefb3..99f589b058 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java @@ -1,6 +1,7 @@ package com.alibaba.druid.filter.wall; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -51,12 +52,18 @@ public abstract class WallProvider { public abstract WallVisitor createWallVisitor(); public boolean check(String sql, boolean throwException) throws WallRuntimeException { + List violations = check(sql); + return violations.size() > 0; + } + + public List check(String sql) { // first step, check whiteList boolean isWhite = whiteContains(sql); if (isWhite) { - return true; + return Collections.emptyList(); } + SQLStatementParser parser = createParser(sql); parser.getLexer().setAllowComment(false); // permit comment @@ -65,26 +72,15 @@ public abstract class WallProvider { try { parser.parseStatementList(statementList); } catch (NotAllowCommentException e) { - if (throwException) { - throw new WallRuntimeException("not allow comment : " + sql); - } - - return false; + return Collections.singletonList(new IllegalSQLObjectViolation(sql)); } if (parser.getLexer().token() != Token.EOF) { - if (throwException) { - throw new WallRuntimeException("illegal statement : " + sql); - } - - return false; + return Collections.singletonList(new IllegalSQLObjectViolation(sql)); } - if (statementList.size() > 1) { - if (throwException) { - throw new WallRuntimeException("multi-statement : " + sql); - } - return false; + if (statementList.size() > 1) { + return Collections.singletonList(new IllegalSQLObjectViolation(sql)); } SQLStatement stmt = statementList.get(0); @@ -93,20 +89,13 @@ public abstract class WallProvider { stmt.accept(visitor); - if (visitor.getViolations().size() > 0) { - if (throwException) { - Violation violation = visitor.getViolations().get(0); - throw new WallRuntimeException(violation.toString()); - } else { - return false; + if (visitor.getViolations().size() == 0) { + if (sql.length() < whiteSqlMaxLength) { + this.addWhiteSql(sql); } } - if (sql.length() < whiteSqlMaxLength) { - this.addWhiteSql(sql); - } - - return true; + return visitor.getViolations(); } } diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallUtils.java b/src/main/java/com/alibaba/druid/filter/wall/WallUtils.java index 22e2e3df38..c629e5e5d8 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/WallUtils.java +++ b/src/main/java/com/alibaba/druid/filter/wall/WallUtils.java @@ -1,5 +1,7 @@ package com.alibaba.druid.filter.wall; +import java.util.List; + import com.alibaba.druid.filter.wall.spi.MySqlWallProvider; import com.alibaba.druid.filter.wall.spi.OracleWallProvider; @@ -7,21 +9,25 @@ public class WallUtils { public static boolean isValidateMySql(String sql) { MySqlWallProvider provider = new MySqlWallProvider(); - return provider.check(sql, false); + List violations = provider.check(sql); + return violations.size() == 0; } public static boolean isValidateMySql(String sql, WallConfig config) { MySqlWallProvider provider = new MySqlWallProvider(config); - return provider.check(sql, false); + List violations = provider.check(sql); + return violations.size() == 0; } public static boolean isValidateOracle(String sql) { OracleWallProvider provider = new OracleWallProvider(); - return provider.check(sql, false); + List violations = provider.check(sql); + return violations.size() == 0; } public static boolean isValidateOracle(String sql, WallConfig config) { OracleWallProvider provider = new OracleWallProvider(config); - return provider.check(sql, false); + List violations = provider.check(sql); + return violations.size() == 0; } } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitFunctionTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitFunctionTest.java index 3fb3e297cd..8f6b152a0c 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitFunctionTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitFunctionTest.java @@ -4,6 +4,7 @@ import junit.framework.TestCase; import org.junit.Assert; +import com.alibaba.druid.filter.wall.WallConfig; import com.alibaba.druid.filter.wall.WallUtils; /** @@ -17,4 +18,10 @@ public class OracleWallPermitFunctionTest extends TestCase { Assert.assertFalse(WallUtils.isValidateOracle("select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual")); } + public void test_permitTable_allow() throws Exception { + WallConfig config = new WallConfig(); + config.setFunctionCheck(false); + Assert.assertTrue(WallUtils.isValidateOracle("select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual", config)); + } + } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitObjectTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitObjectTest.java index 9777b6a9c4..dc6fa4adc6 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitObjectTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/OracleWallPermitObjectTest.java @@ -4,6 +4,7 @@ import junit.framework.TestCase; import org.junit.Assert; +import com.alibaba.druid.filter.wall.WallConfig; import com.alibaba.druid.filter.wall.WallUtils; /** @@ -22,4 +23,14 @@ public class OracleWallPermitObjectTest extends TestCase { Assert.assertFalse(WallUtils.isValidateOracle("select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES()")); } + public void test_permitTable_allow() throws Exception { + WallConfig config = new WallConfig(); + config.setObjectCheck(false); + Assert.assertTrue(WallUtils.isValidateOracle("select sys.LinxReadFile('c:/boot.ini') from dual", config)); + Assert.assertTrue(WallUtils.isValidateOracle("select sys.LinxRunCMD('cmd /c net user linx /add') from dual", config)); + Assert.assertTrue(WallUtils.isValidateOracle("select utl_inaddr.get_host_address from DUAL", config)); + Assert.assertTrue(WallUtils.isValidateOracle("select TO_CHAR(utl_inaddr.get_host_address) from DUAL", config)); + Assert.assertTrue(WallUtils.isValidateOracle("SELECT SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT'.PUT(:P1));", config)); + Assert.assertTrue(WallUtils.isValidateOracle("select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES()", config)); + } }