This commit is contained in:
温少
2012-03-17 23:05:19 +08:00
5 changed files with 66 additions and 40 deletions
@@ -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<Violation> 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;
}
}
@@ -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<Violation> violations = check(sql);
return violations.size() > 0;
}
public List<Violation> 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.<Violation>singletonList(new IllegalSQLObjectViolation(sql));
}
if (parser.getLexer().token() != Token.EOF) {
if (throwException) {
throw new WallRuntimeException("illegal statement : " + sql);
}
return false;
return Collections.<Violation>singletonList(new IllegalSQLObjectViolation(sql));
}
if (statementList.size() > 1) {
if (throwException) {
throw new WallRuntimeException("multi-statement : " + sql);
}
return false;
if (statementList.size() > 1) {
return Collections.<Violation>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();
}
}
@@ -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<Violation> 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<Violation> violations = provider.check(sql);
return violations.size() == 0;
}
public static boolean isValidateOracle(String sql) {
OracleWallProvider provider = new OracleWallProvider();
return provider.check(sql, false);
List<Violation> 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<Violation> violations = provider.check(sql);
return violations.size() == 0;
}
}
@@ -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));
}
}
@@ -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));
}
}