mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-08 16:57:09 +08:00
fix(data): 完善 SQL 注入验证工具类
This commit is contained in:
@@ -16,17 +16,24 @@
|
||||
|
||||
package top.continew.starter.data.core.util;
|
||||
|
||||
import java.util.Objects;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* SQL 注入验证工具类
|
||||
*
|
||||
* @author hubin
|
||||
* @author hubin(<a href="https://github.com/baomidou/mybatis-plus">MyBatis Plus</a>)
|
||||
* @author zhoujf(<a href="https://github.com/jeecgboot/JeecgBoot">JeecgBoot</a>)
|
||||
* @author Charles7c
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public class SqlInjectionUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SqlInjectionUtils.class);
|
||||
|
||||
/**
|
||||
* SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
|
||||
*/
|
||||
@@ -39,6 +46,23 @@ public class SqlInjectionUtils {
|
||||
private static final Pattern SQL_COMMENT_PATTERN = Pattern
|
||||
.compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* SQL 语法关键字
|
||||
*/
|
||||
private static final String SQL_SYNTAX_KEYWORD = "and |exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|--";
|
||||
|
||||
/**
|
||||
* SQL 函数检查正则
|
||||
*/
|
||||
private static final String[] SQL_FUNCTION_PATTERN = new String[] {"chr\\s*\\(", "mid\\s*\\(", " char\\s*\\(",
|
||||
"sleep\\s*\\(", "user\\s*\\(", "show\\s+tables", "user[\\s]*\\([\\s]*\\)", "show\\s+databases",
|
||||
"sleep\\(\\d*\\)", "sleep\\(.*\\)",};
|
||||
|
||||
private static final String MESSAGE_TEMPLATE = "SQL 注入检查: 检查值=>{}<=存在 SQL 注入关键字, 关键字=>{}<=";
|
||||
|
||||
private SqlInjectionUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查参数是否存在 SQL 注入
|
||||
*
|
||||
@@ -46,8 +70,59 @@ public class SqlInjectionUtils {
|
||||
* @return true:非法;false:合法
|
||||
*/
|
||||
public static boolean check(String value) {
|
||||
Objects.requireNonNull(value);
|
||||
// 处理是否包含 SQL 注释字符 || 检查是否包含 SQ L注入敏感字符
|
||||
return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
|
||||
return check(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查参数是否存在 SQL 注入
|
||||
*
|
||||
* @param value 检查参数
|
||||
* @param customKeyword 自定义关键字
|
||||
* @return true:非法;false:合法
|
||||
*/
|
||||
public static boolean check(String value, String customKeyword) {
|
||||
if (CharSequenceUtil.isBlank(value)) {
|
||||
return false;
|
||||
}
|
||||
// 处理是否包含 SQL 注释字符 || 检查是否包含 SQL 注入敏感字符
|
||||
if (SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find()) {
|
||||
log.warn("SQL 注入检查: 检查值=>{}<=存在 SQL 注释字符或 SQL 注入敏感字符", value);
|
||||
return true;
|
||||
}
|
||||
// 转换成小写再进行比较
|
||||
value = value.toLowerCase().trim();
|
||||
// 检查是否包含 SQL 语法关键字
|
||||
if (checkKeyword(value, SQL_SYNTAX_KEYWORD.split("\\|"))) {
|
||||
return true;
|
||||
}
|
||||
// 检查是否包含自定义关键字
|
||||
if (CharSequenceUtil.isNotBlank(customKeyword) && checkKeyword(value, customKeyword.split("\\|"))) {
|
||||
return true;
|
||||
}
|
||||
// 检查是否包含 SQL 注入敏感字符
|
||||
for (String pattern : SQL_FUNCTION_PATTERN) {
|
||||
if (Pattern.matches(".*" + pattern + ".*", value)) {
|
||||
log.warn(MESSAGE_TEMPLATE, value, pattern);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查参数是否存在关键字
|
||||
*
|
||||
* @param value 检查参数
|
||||
* @param keywords 关键字列表
|
||||
* @return true:非法;false:合法
|
||||
*/
|
||||
private static boolean checkKeyword(String value, String[] keywords) {
|
||||
for (String keyword : keywords) {
|
||||
if (value.contains(keyword)) {
|
||||
log.warn(MESSAGE_TEMPLATE, value, keyword);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user