mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
sql wall
This commit is contained in:
@@ -19,11 +19,13 @@ import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
|
||||
@@ -90,27 +92,33 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
public List<Violation> getViolations() {
|
||||
return violations;
|
||||
}
|
||||
|
||||
|
||||
public boolean visit(SQLPropertyExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectQueryBlock x) {
|
||||
if (x.getWhere() != null) {
|
||||
x.getWhere().setParent(x);
|
||||
}
|
||||
WallVisitorUtils.checkCondition(this, x.getWhere());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLSelectGroupByClause x) {
|
||||
WallVisitorUtils.checkCondition(this, x.getHaving());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(MySqlSelectGroupBy x) {
|
||||
WallVisitorUtils.checkCondition(this, x.getHaving());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlSelectQueryBlock x) {
|
||||
return visit((SQLSelectQueryBlock) x);
|
||||
|
||||
@@ -20,11 +20,14 @@ import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVIsitorAdapter;
|
||||
|
||||
@@ -108,8 +111,6 @@ public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVi
|
||||
|
||||
// executeQuery
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,6 +141,23 @@ public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVi
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLSelectGroupByClause x) {
|
||||
WallVisitorUtils.checkCondition(this, x.getHaving());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectQueryBlock x) {
|
||||
WallVisitorUtils.checkCondition(this, x.getWhere());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleSelectQueryBlock x) {
|
||||
return visit((SQLSelectQueryBlock) x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLUnionQuery x) {
|
||||
if (WallVisitorUtils.queryBlockFromIsNull(x.getLeft()) || WallVisitorUtils.queryBlockFromIsNull(x.getRight())) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
@@ -29,6 +30,7 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
|
||||
@@ -50,7 +52,11 @@ public class WallVisitorUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLBinaryOpExpr x) {
|
||||
public static void checkCondition(WallVisitor visitor, SQLExpr x) {
|
||||
if (x == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE == getValue(x)) {
|
||||
visitor.getViolations().add(new IllegalSQLObjectViolation(SQLUtils.toSQLString(x)));
|
||||
}
|
||||
@@ -338,7 +344,8 @@ public class WallVisitorUtils {
|
||||
|
||||
public static boolean queryBlockFromIsNull(SQLSelectQuery query) {
|
||||
if (query instanceof SQLSelectQueryBlock) {
|
||||
SQLTableSource from = ((SQLSelectQueryBlock) query).getFrom();
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;
|
||||
SQLTableSource from = queryBlock.getFrom();
|
||||
|
||||
if (from == null) {
|
||||
return true;
|
||||
@@ -356,6 +363,26 @@ public class WallVisitorUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean allIsConst = true;
|
||||
for (SQLSelectItem item : queryBlock.getSelectList()) {
|
||||
if (getValue(item.getExpr()) == null) {
|
||||
allIsConst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allIsConst) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -234,4 +234,6 @@ UTL_REF
|
||||
UTL_SMTP
|
||||
UTL_SPADV
|
||||
UTL_TCP
|
||||
UTL_URL
|
||||
UTL_URL
|
||||
SYS
|
||||
SYSTEM
|
||||
@@ -1 +1,2 @@
|
||||
SYS
|
||||
SYS
|
||||
SYSTEM
|
||||
@@ -16,6 +16,7 @@ public class OracleWallPermitObjectTest extends TestCase {
|
||||
public void test_permitTable() throws Exception {
|
||||
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));"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 WallHavingTest extends TestCase {
|
||||
private String sql = "SELECT F1, COUNT(*) FROM T GROUP BY F1 HAVING 1 = 1";
|
||||
|
||||
public void testMySql() throws Exception {
|
||||
Assert.assertFalse(WallUtils.isValidateMySql(sql));
|
||||
}
|
||||
|
||||
public void testORACLE() throws Exception {
|
||||
Assert.assertFalse(WallUtils.isValidateOracle(sql));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.alibaba.druid.bvt.filter.wall;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.filter.wall.WallUtils;
|
||||
|
||||
/**
|
||||
* 这个场景,被攻击者用于测试当前SQL拥有多少字段
|
||||
* @author wenshao
|
||||
*
|
||||
*/
|
||||
public class WallUnionTest4 extends TestCase {
|
||||
|
||||
public void testMySql() throws Exception {
|
||||
Assert.assertFalse(WallUtils.isValidateMySql("SELECT id, product FROM T1 t UNION (SELECT * FROM (SELECT 1,'x') X)"));
|
||||
}
|
||||
|
||||
public void testORACLE() throws Exception {
|
||||
Assert.assertFalse(WallUtils.isValidateOracle("SELECT id, product FROM T1 t UNION (SELECT * FROM (SELECT 1,'x') X)"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user