add sql wall suppport

This commit is contained in:
温少
2012-03-16 21:27:05 +08:00
9 changed files with 226 additions and 47 deletions
@@ -3,6 +3,7 @@ package com.alibaba.druid.filter.wall;
import java.sql.SQLException;
import java.util.Properties;
import com.alibaba.druid.DruidRuntimeException;
import com.alibaba.druid.filter.FilterAdapter;
import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.filter.wall.spi.MySqlWallProvider;
@@ -17,13 +18,45 @@ import com.alibaba.druid.util.JdbcUtils;
public class WallFilter extends FilterAdapter {
private boolean inited = false;
private WallProvider provider;
private boolean loadDefault;
private boolean loadExtend;
@Override
public void init(DataSourceProxy dataSource) {
this.dataSource = dataSource;
provider = createWallProvider(dataSource.getDbType());
this.inited = true;
}
public boolean isLoadDefault() {
return loadDefault;
}
public void checkInit() {
if (inited) {
throw new DruidRuntimeException("wall filter is inited");
}
}
public void setLoadDefault(boolean loadDefault) {
checkInit();
this.loadDefault = loadDefault;
}
public boolean isLoadExtend() {
return loadExtend;
}
public void setLoadExtend(boolean loadExtend) {
checkInit();
this.loadExtend = loadExtend;
}
@Override
@@ -168,11 +201,11 @@ public class WallFilter extends FilterAdapter {
public WallProvider createWallProvider(String dbType) {
if (JdbcUtils.MYSQL.equals(dbType)) {
return new MySqlWallProvider();
return new MySqlWallProvider(this.loadDefault, this.loadExtend);
}
if (JdbcUtils.ORACLE.equals(dbType)) {
return new OracleWallProvider();
return new OracleWallProvider(this.loadDefault, this.loadExtend);
}
throw new IllegalStateException("dbType not support : " + dbType);
@@ -8,19 +8,32 @@ import com.alibaba.druid.sql.parser.SQLStatementParser;
public class MySqlWallProvider extends WallProvider {
public MySqlWallProvider(){
loadDefault();
this(true, true);
}
public MySqlWallProvider(boolean loadDefault, boolean loadExtend){
if (loadDefault) {
loadDefault();
}
if (loadExtend) {
loadExtend();
}
}
public void loadExtend() {
WallVisitorUtils.loadResource(this.permitNames, "META-INF/druid-filter-wall-permit-name-mysql.txt");
WallVisitorUtils.loadResource(this.permitSchemas, "META-INF/druid-filter-wall-permit-schema-mysql.txt");
WallVisitorUtils.loadResource(this.permitFunctions, "META-INF/druid-filter-wall-permit-function-mysql.txt");
WallVisitorUtils.loadResource(this.permitTables, "META-INF/druid-filter-wall-permit-table-mysql.txt");
WallVisitorUtils.loadResource(this.permitObjects, "META-INF/druid-filter-wall-permit-object-mysql.txt");
}
public void loadDefault() {
WallVisitorUtils.loadResource(this.permitNames, "META-INF/druid-filter-wall-permit-name-mysql-default.txt");
WallVisitorUtils.loadResource(this.permitSchemas, "META-INF/druid-filter-wall-permit-schema-mysql-default.txt");
WallVisitorUtils.loadResource(this.permitFunctions, "META-INF/druid-filter-wall-permit-function-mysql-default.txt");
WallVisitorUtils.loadResource(this.permitFunctions,
"META-INF/druid-filter-wall-permit-function-mysql-default.txt");
WallVisitorUtils.loadResource(this.permitTables, "META-INF/druid-filter-wall-permit-table-mysql-default.txt");
WallVisitorUtils.loadResource(this.permitObjects, "META-INF/druid-filter-wall-permit-object-mysql-default.txt");
}
@@ -8,8 +8,20 @@ import com.alibaba.druid.sql.parser.SQLStatementParser;
public class OracleWallProvider extends WallProvider {
public OracleWallProvider(){
loadDefault();
this(true, true);
}
public OracleWallProvider(boolean loadDefault, boolean loadExtend){
if (loadDefault) {
loadDefault();
}
if (loadExtend) {
loadExtend();
}
}
public void loadExtend() {
WallVisitorUtils.loadResource(this.permitNames, "META-INF/druid-filter-wall-permit-name-oracle.txt");
WallVisitorUtils.loadResource(this.permitSchemas, "META-INF/druid-filter-wall-permit-schema-oracle.txt");
WallVisitorUtils.loadResource(this.permitFunctions, "META-INF/druid-filter-wall-permit-function-oracle.txt");
@@ -17,6 +29,15 @@ public class OracleWallProvider extends WallProvider {
WallVisitorUtils.loadResource(this.permitObjects, "META-INF/druid-filter-wall-permit-object-oracle.txt");
}
public void loadDefault() {
WallVisitorUtils.loadResource(this.permitNames, "META-INF/druid-filter-wall-permit-name-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitSchemas, "META-INF/druid-filter-wall-permit-schema-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitFunctions,
"META-INF/druid-filter-wall-permit-function-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitTables, "META-INF/druid-filter-wall-permit-table-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitObjects, "META-INF/druid-filter-wall-permit-object-oracle-default.txt");
}
@Override
public SQLStatementParser createParser(String sql) {
return new OracleStatementParser(sql);
@@ -27,12 +48,4 @@ public class OracleWallProvider extends WallProvider {
return new OracleWallVisitor(this);
}
public void loadDefault() {
WallVisitorUtils.loadResource(this.permitNames, "META-INF/druid-filter-wall-permit-name-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitSchemas, "META-INF/druid-filter-wall-permit-schema-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitFunctions,
"META-INF/druid-filter-wall-permit-function-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitTables, "META-INF/druid-filter-wall-permit-table-oracle-default.txt");
WallVisitorUtils.loadResource(this.permitObjects, "META-INF/druid-filter-wall-permit-object-oracle-default.txt");
}
}
@@ -41,7 +41,7 @@ import com.alibaba.druid.util.JdbcUtils;
public class WallVisitorUtils {
private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class);
public static void check(WallVisitor visitor, SQLPropertyExpr x) {
if (x.getOwner() instanceof SQLIdentifierExpr) {
String owner = x.getOwner().toString();
@@ -56,7 +56,7 @@ public class WallVisitorUtils {
if (x == null) {
return;
}
if (Boolean.TRUE == getValue(x)) {
visitor.getViolations().add(new IllegalSQLObjectViolation(SQLUtils.toSQLString(x)));
}
@@ -85,15 +85,32 @@ public class WallVisitorUtils {
}
}
if (x.getOperator() == SQLBinaryOperator.Like) {
if (x.getRight() instanceof SQLCharExpr) {
String text = ((SQLCharExpr) x.getRight()).getText();
if (text.length() >= 0) {
for (char ch : text.toCharArray()) {
if (ch != '%') {
return null;
}
}
return true;
}
}
}
if (leftResult == null || rightResult == null) {
return null;
}
if (x.getOperator() == SQLBinaryOperator.Equality) {
if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) {
return true;
}
if (leftResult == null || rightResult == null) {
return null;
}
return leftResult.equals(rightResult);
}
@@ -165,21 +182,8 @@ public class WallVisitorUtils {
}
}
if (x.getOperator() == SQLBinaryOperator.Like) {
if (x.getRight() instanceof SQLCharExpr) {
String text = ((SQLCharExpr) x.getRight()).getText();
if (text.length() >= 0) {
for (char ch : text.toCharArray()) {
if (ch != '%') {
return null;
}
}
return true;
}
}
if (x.getOperator() == SQLBinaryOperator.Concat) {
return leftResult.toString() + rightResult.toString();
}
return null;
@@ -252,6 +256,30 @@ public class WallVisitorUtils {
}
}
if ("chr".equalsIgnoreCase(methodName) && x.getParameters().size() == 1) {
SQLExpr first = x.getParameters().get(0);
Object firstResult = getValue(first);
if (firstResult instanceof Number) {
int intValue = ((Number) firstResult).intValue();
char ch = (char) intValue;
return "" + ch;
}
}
if ("concat".equalsIgnoreCase(methodName)) {
StringBuffer buf = new StringBuffer();
for (SQLExpr expr : x.getParameters()) {
Object value = getValue(expr);
if (value == null) {
return null;
}
buf.append(value.toString());
}
return buf.toString();
}
return null;
}
@@ -302,6 +330,14 @@ public class WallVisitorUtils {
}
public static void check(WallVisitor visitor, SQLMethodInvokeExpr x) {
if (x.getOwner() instanceof SQLIdentifierExpr) {
String owner = x.getOwner().toString();
owner = WallVisitorUtils.form(owner);
if (visitor.containsPermitObjects(owner)) {
visitor.getViolations().add(new IllegalSQLObjectViolation(visitor.toSQL(x)));
}
}
String methodName = x.getMethodName();
if (visitor.getWallProvider().getPermitFunctions().contains(methodName.toLowerCase())) {
@@ -363,8 +399,9 @@ public class WallVisitorUtils {
}
}
}
if (queryBlock.getSelectList().size() == 1 && queryBlock.getSelectList().get(0).getExpr() instanceof SQLAllColumnExpr) {
if (queryBlock.getSelectList().size() == 1
&& queryBlock.getSelectList().get(0).getExpr() instanceof SQLAllColumnExpr) {
if (from instanceof SQLSubqueryTableSource) {
SQLSelectQuery subQuery = ((SQLSubqueryTableSource) from).getSelect().getQuery();
if (queryBlockFromIsNull(subQuery)) {
@@ -372,7 +409,7 @@ public class WallVisitorUtils {
}
}
}
boolean allIsConst = true;
for (SQLSelectItem item : queryBlock.getSelectList()) {
if (getValue(item.getExpr()) == null) {
@@ -14,9 +14,12 @@ import com.alibaba.druid.filter.wall.WallUtils;
public class OracleWallPermitObjectTest extends TestCase {
public void test_permitTable() throws Exception {
Assert.assertFalse(WallUtils.isValidateOracle("select sys.LinxReadFile('c:/boot.ini') from dual"));
Assert.assertFalse(WallUtils.isValidateOracle("select sys.LinxRunCMD('cmd /c net user linx /add') from dual"));
Assert.assertFalse(WallUtils.isValidateOracle("select utl_inaddr.get_host_address from DUAL"));
Assert.assertFalse(WallUtils.isValidateOracle("select TO_CHAR(utl_inaddr.get_host_address) from DUAL"));
Assert.assertFalse(WallUtils.isValidateOracle("SELECT SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT'.PUT(:P1));"));
Assert.assertFalse(WallUtils.isValidateOracle("select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES()"));
}
}
@@ -0,0 +1,24 @@
package com.alibaba.druid.bvt.filter.wall;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.filter.wall.WallUtils;
/**
* 这个场景,检测可疑的Having条件
* @author wenshao
*
*/
public class WallSelectWhereTest3 extends TestCase {
private String sql = "select * from t WHERE FID = 256 AND CHR(67)||CHR(65)||CHR(84) = 'CAT'";
public void testMySql() throws Exception {
Assert.assertTrue(WallUtils.isValidateMySql(sql));
}
public void testORACLE() throws Exception {
Assert.assertTrue(WallUtils.isValidateOracle(sql));
}
}
@@ -0,0 +1,24 @@
package com.alibaba.druid.bvt.filter.wall;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.filter.wall.WallUtils;
/**
* 这个场景,检测可疑的Having条件
* @author wenshao
*
*/
public class WallSelectWhereTest4 extends TestCase {
private String sql = "select * from t WHERE FID = 256 OR CHR(67)||CHR(65)||CHR(84) = 'CAT'";
public void testMySql() throws Exception {
Assert.assertFalse(WallUtils.isValidateMySql(sql));
}
public void testORACLE() throws Exception {
Assert.assertFalse(WallUtils.isValidateOracle(sql));
}
}
@@ -0,0 +1,24 @@
package com.alibaba.druid.bvt.filter.wall;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.filter.wall.WallUtils;
/**
* 这个场景,检测可疑的Having条件
* @author wenshao
*
*/
public class WallSelectWhereTest5 extends TestCase {
private String sql = "select * from t WHERE FID = 256 OR CONCAT(CHR(67)||CHR(65)||CHR(84), '-DOG') = 'CAT-DOG'";
public void testMySql() throws Exception {
Assert.assertFalse(WallUtils.isValidateMySql(sql));
}
public void testORACLE() throws Exception {
Assert.assertFalse(WallUtils.isValidateOracle(sql));
}
}
@@ -18,23 +18,31 @@ public class WallVisitorUtilsTest extends TestCase {
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("f1 like '%%'")));
Assert.assertEquals(null, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 AND f1 like '%%'")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 OR f1 like '%%'")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("1 < 2")));
Assert.assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 < 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 <= 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 > 1")));
Assert.assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 > 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("2 >= 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("len('44') > 0")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("len('44') >= 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) > 0")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) >= 0")));
Assert.assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) < 0")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("NOT (select count(*) from t) < 0")));
Assert.assertEquals(Boolean.TRUE,
WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) >= 0")));
Assert.assertEquals(Boolean.FALSE,
WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) < 0")));
Assert.assertEquals(Boolean.TRUE,
WallVisitorUtils.getValue(SQLUtils.toSQLExpr("NOT (select count(*) from t) < 0")));
//
}
public void test_chr() throws Exception {
Assert.assertEquals("CAT", WallVisitorUtils.getValue(SQLUtils.toSQLExpr("CHR(67)||CHR(65)||CHR(84)")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("CHR(67)||CHR(65)||CHR(84) = 'CAT'")));
}
}