diff --git a/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java index 25a8cd2b0f..f88f3ab421 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/filter/wall/spi/WallVisitorUtils.java @@ -209,6 +209,19 @@ public class WallVisitorUtils { return ((String) firstValue).length(); } } + + if ("if".equalsIgnoreCase(methodName) && x.getParameters().size() == 3) { + SQLExpr first = x.getParameters().get(0); + Object firstResult = getValue(first); + + if (Boolean.TRUE == firstResult) { + return getValue(x.getParameters().get(1)); + } + + if (Boolean.FALSE == firstResult) { + getValue(x.getParameters().get(2)); + } + } return null; } @@ -277,6 +290,8 @@ public class WallVisitorUtils { if (propExpr.getOwner() instanceof SQLIdentifierExpr) { String ownerName = ((SQLIdentifierExpr) propExpr.getOwner()).getName(); + + ownerName = form(ownerName); if (visitor.getPermitSchemas().contains(ownerName.toLowerCase())) { visitor.getViolations().add(new IllegalSQLObjectViolation(visitor.toSQL(x))); @@ -327,6 +342,9 @@ public class WallVisitorUtils { if (name.startsWith("\"") && name.endsWith("\"")) { name = name.substring(1, name.length() - 1); } + if (name.startsWith("`") && name.endsWith("`")) { + name = name.substring(1, name.length() - 1); + } name = name.toLowerCase(); return name; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index a86506fbfd..c9dd9a68eb 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -273,9 +273,9 @@ public class SQLExprParser extends SQLParser { accept(Token.RPAREN); notTarget = exprRest(notTarget); - + sqlExpr = new SQLNotExpr(notTarget); - + return primaryRest(sqlExpr); } else { SQLExpr restExpr = expr(); @@ -468,6 +468,11 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.DOT) { lexer.nextToken(); + if (expr instanceof SQLCharExpr) { + String text = ((SQLCharExpr) expr).getText(); + expr = new SQLIdentifierExpr(text); + } + expr = dotRest(expr); return primaryRest(expr); } else if (lexer.token() == Token.COLONEQ) { @@ -635,7 +640,11 @@ public class SQLExprParser extends SQLParser { throw new ParserException("error, " + lexer.token()); } - name = new SQLPropertyExpr(name, lexer.stringVal()); + if (lexer.token() == Token.LITERAL_ALIAS) { + name = new SQLPropertyExpr(name, '"' + lexer.stringVal() + '"'); + } else { + name = new SQLPropertyExpr(name, lexer.stringVal()); + } lexer.nextToken(); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index e8938ce37b..44f7986214 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -227,6 +227,11 @@ public class SQLSelectParser extends SQLParser { } private void parseTableSourceQueryTableExpr(SQLExprTableSource tableReference) throws ParserException { + if (lexer.token() == Token.LITERAL_ALIAS || lexer.token() == Token.IDENTIFIED || lexer.token() == Token.LITERAL_CHARS) { + tableReference.setExpr(this.createExprParser().name()); + return; + } + tableReference.setExpr(expr()); } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallPermitTableTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallPermitTableTest.java new file mode 100644 index 0000000000..5ce75768a7 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallPermitTableTest.java @@ -0,0 +1,29 @@ +package com.alibaba.druid.bvt.filter.wall; + +import org.junit.Assert; + +import com.alibaba.druid.filter.wall.WallUtils; + +import junit.framework.TestCase; + +/** + * 这个场景测试访问MySql系统表 + * + * @author admin + */ +public class MySqlWallPermitTableTest extends TestCase { + + public void test_permitTable() throws Exception { + Assert.assertFalse(WallUtils.isValidateMySql("SELECT User,Password FROM mysql.user")); + Assert.assertFalse(WallUtils.isValidateMySql("SELECT User,Password FROM `mysql`.`user`")); + Assert.assertFalse(WallUtils.isValidateMySql("SELECT User,Password FROM \"mysql\".\"user\"")); + Assert.assertFalse(WallUtils.isValidateMySql("SELECT User,Password FROM MYSQL.USER")); + } + + public void test_permitTable_subquery() throws Exception { + Assert.assertFalse(WallUtils.isValidateMySql("select * from(SELECT User,Password FROM mysql.user) a")); + Assert.assertFalse(WallUtils.isValidateMySql("select * from(SELECT User,Password FROM `mysql`.`user`) a")); + Assert.assertFalse(WallUtils.isValidateMySql("select * from(SELECT User,Password FROM \"mysql\".\"user\") a")); + Assert.assertFalse(WallUtils.isValidateMySql("select * from(SELECT User,Password FROM MYSQL.USER) a")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest2.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest2.java new file mode 100644 index 0000000000..982115969f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest2.java @@ -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 WallUnionTest2 extends TestCase { + + public void testMySql() throws Exception { + Assert.assertFalse(WallUtils.isValidateMySql("select f1, f2 from t union select 1, 2 where 1 = 1")); + } + + public void testOracle() throws Exception { + Assert.assertFalse(WallUtils.isValidateOracle("select f1, f2 from t union select 1, 2 where 1 = 1")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest3.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest3.java new file mode 100644 index 0000000000..6a2027ca75 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest3.java @@ -0,0 +1,21 @@ +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 WallUnionTest3 extends TestCase { + + public void testMySql() throws Exception { + Assert.assertFalse(WallUtils.isValidateMySql("SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x'")); + Assert.assertFalse(WallUtils.isValidateMySql("SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x';")); + Assert.assertFalse(WallUtils.isValidateMySql("SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x'/*,10 ;")); + } +} diff --git a/src/test/java/com/alibaba/druid/sql/TestOnlineSQLTest3.java b/src/test/java/com/alibaba/druid/sql/TestOnlineSQLTest3.java index 95ffbc18b1..f2db86feda 100644 --- a/src/test/java/com/alibaba/druid/sql/TestOnlineSQLTest3.java +++ b/src/test/java/com/alibaba/druid/sql/TestOnlineSQLTest3.java @@ -7,15 +7,18 @@ import java.sql.Statement; import junit.framework.TestCase; +import com.alibaba.druid.util.JdbcUtils; + public class TestOnlineSQLTest3 extends TestCase { - private String url = "jdbc:mysql://10.249.192.221/test"; - private String user = "dragoon"; - private String password = "dragoon"; + private String url = "jdbc:mysql://10.20.144.27/dragoon_v25_masterdb"; + private String user = "dragoon_test"; + private String password = "dragoon_test"; protected Connection conn; public void setUp() throws Exception { + Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(url, user, password); } @@ -27,23 +30,15 @@ public class TestOnlineSQLTest3 extends TestCase { } public void test_0() throws Exception { - String sql = "SELECT * FROM m_sql_const"; +// ResultSet rs = conn.getMetaData().getTables(null, null, null, null); +// JdbcUtils.printResultSet(rs); + + String sql = "SELECT User,Password FROM mysql.user;"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); - while (rs.next()) { - long id = rs.getLong(1); - String value = rs.getString(2); - handle(id, value); - } - rs.close(); - + JdbcUtils.printResultSet(rs); + stmt.close(); } - - void handle(long id, String value) { - String sql = value.toString(); - - System.out.println(sql); - } }