mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve sqlwall
This commit is contained in:
@@ -41,6 +41,7 @@ public class WallConfig implements WallConfigMBean {
|
||||
private boolean alterTableAllow = true;
|
||||
private boolean renameTableAllow = true;
|
||||
private boolean hintAllow = true;
|
||||
private boolean lockTableAllow = true;
|
||||
|
||||
private boolean conditionAndAlwayTrueAllow = false;
|
||||
private boolean conditionAndAlwayFalseAllow = false;
|
||||
@@ -752,4 +753,12 @@ public class WallConfig implements WallConfigMBean {
|
||||
this.inited = inited;
|
||||
}
|
||||
|
||||
public boolean isLockTableAllow() {
|
||||
return lockTableAllow;
|
||||
}
|
||||
|
||||
public void setLockTableAllow(boolean lockTableAllow) {
|
||||
this.lockTableAllow = lockTableAllow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -445,87 +445,7 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCommentHint x) {
|
||||
if(!provider.getConfig().isHintAllow()) {
|
||||
addViolation(new IllegalSQLObjectViolation(ErrorCode.EVIL_HINTS, "hint not allow", SQLUtils.toMySqlString(x)));
|
||||
return true;
|
||||
}
|
||||
|
||||
String text = x.getText();
|
||||
text = text.trim();
|
||||
if (text.startsWith("!")) {
|
||||
text = text.substring(1);
|
||||
}
|
||||
|
||||
if (text.length() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Character.isDigit(text.charAt(0))) {
|
||||
addViolation(new IllegalSQLObjectViolation(ErrorCode.EVIL_HINTS, "evil hints", SQLUtils.toMySqlString(x)));
|
||||
}
|
||||
|
||||
text = text.toLowerCase();
|
||||
|
||||
for (int i = 0; i < text.length(); ++i) {
|
||||
char ch = text.charAt(i);
|
||||
switch (ch) {
|
||||
case ';':
|
||||
case '>':
|
||||
case '=':
|
||||
case '<':
|
||||
case '&':
|
||||
case '|':
|
||||
case '^':
|
||||
case '\n':
|
||||
case '.':
|
||||
case '(':
|
||||
addViolation(new IllegalSQLObjectViolation(ErrorCode.EVIL_HINTS, "evil hints",
|
||||
SQLUtils.toMySqlString(x)));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (text.indexOf("or") != -1 //
|
||||
|| text.indexOf("and") != -1 //
|
||||
|| text.indexOf("union") != -1 //
|
||||
|| text.indexOf("xor") != -1 //
|
||||
|
||||
|| text.indexOf("select") != -1 //
|
||||
|| text.indexOf("delete") != -1 //
|
||||
|| text.indexOf("insert") != -1 //
|
||||
|| text.indexOf("update") != -1 //
|
||||
|| text.indexOf("into") != -1 //
|
||||
|
||||
|| text.indexOf("create") != -1 //
|
||||
|| text.indexOf("drop") != -1 //
|
||||
|| text.indexOf("alter") != -1 //
|
||||
|| text.indexOf("truncate") != -1 //
|
||||
|
||||
|| text.indexOf("information_schema") != -1 //
|
||||
|| text.indexOf("mysql") != -1 //
|
||||
|| text.indexOf("performance_schema") != -1 //
|
||||
|
||||
|| text.indexOf("sleep") != -1 //
|
||||
|| text.indexOf("benchmark") != -1 //
|
||||
|| text.indexOf("load_file") != -1 //
|
||||
|| text.indexOf("version") != -1 //
|
||||
|| text.indexOf("database") != -1 //
|
||||
|| text.indexOf("schema") != -1 //
|
||||
|| text.indexOf("system_user") != -1 //
|
||||
|| text.indexOf("session_user") != -1 //
|
||||
|| text.indexOf("current_user") != -1 //
|
||||
|| text.indexOf("user") != -1 //
|
||||
|| text.indexOf("xmltype") != -1 //
|
||||
|| text.indexOf("receive_message") != -1 //
|
||||
|
||||
|| text.indexOf("version_compile_os") != -1 //
|
||||
|| text.indexOf("basedir") != -1 //
|
||||
|| text.indexOf("datadir") != -1 //
|
||||
) {
|
||||
addViolation(new IllegalSQLObjectViolation(ErrorCode.EVIL_HINTS, "evil hints", SQLUtils.toMySqlString(x)));
|
||||
}
|
||||
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,22 @@
|
||||
*/
|
||||
package com.alibaba.druid.wall.spi;
|
||||
|
||||
import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLCommentHint;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
@@ -84,6 +99,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlHintStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
|
||||
@@ -92,11 +108,13 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowGrantsStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStatement;
|
||||
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.sqlserver.ast.stmt.SQLServerExecStatement;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
|
||||
@@ -116,25 +134,14 @@ import com.alibaba.druid.wall.WallVisitor;
|
||||
import com.alibaba.druid.wall.violation.ErrorCode;
|
||||
import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;
|
||||
|
||||
public class WallVisitorUtils {
|
||||
|
||||
private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class);
|
||||
private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class);
|
||||
|
||||
public final static String HAS_TRUE_LIKE = "hasTrueLike";
|
||||
public final static String HAS_TRUE_LIKE = "hasTrueLike";
|
||||
|
||||
public final static String[] whiteHints = { "LOCAL", "TEMPORARY", "SQL_NO_CACHE", "SQL_CACHE", "HIGH_PRIORITY",
|
||||
"LOW_PRIORITY", "STRAIGHT_JOIN", "SQL_BUFFER_RESULT", "SQL_BIG_RESULT", "SQL_SMALL_RESULT", "DELAYED" };
|
||||
|
||||
public static void check(WallVisitor visitor, SQLInListExpr x) {
|
||||
|
||||
@@ -2405,14 +2412,84 @@ public class WallVisitorUtils {
|
||||
allow = config.isHintAllow();
|
||||
denyMessage = "hint not allow";
|
||||
errorCode = ErrorCode.HINT_NOT_ALLOW;
|
||||
} else if (x instanceof MySqlLockTableStatement) {
|
||||
allow = config.isLockTableAllow();
|
||||
denyMessage = "lock table not allow";
|
||||
errorCode = ErrorCode.LOCK_TABLE_NOT_ALLOW;
|
||||
} else {
|
||||
allow = config.isNoneBaseStatementAllow();
|
||||
errorCode = ErrorCode.NONE_BASE_STATEMENT_NOT_ALLOW;
|
||||
denyMessage = x.getClass() + " not allow";
|
||||
}
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
addViolation(visitor, errorCode, denyMessage, x);
|
||||
}
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLCommentHint x) {
|
||||
if (!visitor.getConfig().isHintAllow()) {
|
||||
addViolation(visitor, ErrorCode.EVIL_HINTS, "hint not allow", x);
|
||||
return;
|
||||
}
|
||||
|
||||
String text = x.getText();
|
||||
text = text.trim();
|
||||
if (text.startsWith("!")) {
|
||||
text = text.substring(1);
|
||||
}
|
||||
|
||||
if (text.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
for (; pos < text.length(); pos++) {
|
||||
char ch = text.charAt(pos);
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == 5) {
|
||||
text = text.substring(5);
|
||||
text = text.trim();
|
||||
}
|
||||
|
||||
text = text.toUpperCase();
|
||||
|
||||
boolean isWhite = false;
|
||||
for (String hint : whiteHints) {
|
||||
if (text.equals(hint)) {
|
||||
isWhite = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isWhite) {
|
||||
if (text.startsWith("FORCE INDEX") || text.startsWith("IGNORE INDEX")) {
|
||||
isWhite = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isWhite) {
|
||||
if (text.startsWith("SET")) {
|
||||
SQLStatementParser parser = new MySqlStatementParser(text);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
if (statementList != null && statementList.size() > 0) {
|
||||
SQLStatement statement = statementList.get(0);
|
||||
if (statement instanceof SQLSetStatement || statement instanceof MySqlSetCharSetStatement
|
||||
|| statement instanceof MySqlSetNamesStatement) {
|
||||
isWhite = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isWhite) {
|
||||
addViolation(visitor, ErrorCode.EVIL_HINTS, "hint not allow", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public interface ErrorCode {
|
||||
public final static int DROP_TABLE_NOT_ALLOW = 1103;
|
||||
public final static int COMMENT_STATEMENT_NOT_ALLOW = 1104;
|
||||
public final static int RENAME_TABLE_NOT_ALLOW = 1105;
|
||||
public final static int LOCK_TABLE_NOT_ALLOW = 1105;
|
||||
|
||||
public final static int LIMIT_ZERO = 2200;
|
||||
public final static int MULTI_STATEMENT = 2201;
|
||||
|
||||
@@ -53,5 +53,28 @@ public class MySqlWallTest_hint extends TestCase {
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(sql, config));
|
||||
}
|
||||
|
||||
public void test_true_4() throws Exception {
|
||||
WallConfig config = new WallConfig();
|
||||
config.setHintAllow(true);
|
||||
config.setMultiStatementAllow(true);
|
||||
String sql = "LOCK TABLES `m_rpt_adgroupeffect` READ /*!32311 LOCAL */";
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(sql, config)); //
|
||||
}
|
||||
|
||||
public void test_true_5() throws Exception {
|
||||
WallConfig config = new WallConfig();
|
||||
config.setHintAllow(true);
|
||||
config.setMultiStatementAllow(true);
|
||||
String sql = "DROP TABLE IF EXISTS `item_similarity`;"//
|
||||
+ "\n/*!40101 SET @saved_cs_client = @@character_set_client */;"//
|
||||
+ "\n/*!40101 SET character_set_client = utf8 */;" //
|
||||
+ "\nCREATE TABLE `item_similarity` ("//
|
||||
+ " `id` bigint(20) unsigned NOT NULL, "//
|
||||
+ " `sellerId` bigint(20) DEFAULT NULL,"//
|
||||
+ " PRIMARY KEY (`id`)" //
|
||||
+ " ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"//
|
||||
+ " \n/*!40101 SET character_set_client = @saved_cs_client */;";
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(sql, config)); //
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user