mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
add sql wall suppport
This commit is contained in:
@@ -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'")));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user