mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-10-24 18:57:13 +08:00
fix(data): 完善 SQL 注入验证工具类
This commit is contained in:
@@ -16,17 +16,24 @@
|
|||||||
|
|
||||||
package top.continew.starter.data.core.util;
|
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;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SQL 注入验证工具类
|
* 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
|
* @since 2.5.2
|
||||||
*/
|
*/
|
||||||
public class SqlInjectionUtils {
|
public class SqlInjectionUtils {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SqlInjectionUtils.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
|
* SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
|
||||||
*/
|
*/
|
||||||
@@ -39,6 +46,23 @@ public class SqlInjectionUtils {
|
|||||||
private static final Pattern SQL_COMMENT_PATTERN = Pattern
|
private static final Pattern SQL_COMMENT_PATTERN = Pattern
|
||||||
.compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);
|
.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 注入
|
* 检查参数是否存在 SQL 注入
|
||||||
*
|
*
|
||||||
@@ -46,8 +70,59 @@ public class SqlInjectionUtils {
|
|||||||
* @return true:非法;false:合法
|
* @return true:非法;false:合法
|
||||||
*/
|
*/
|
||||||
public static boolean check(String value) {
|
public static boolean check(String value) {
|
||||||
Objects.requireNonNull(value);
|
return check(value, null);
|
||||||
// 处理是否包含 SQL 注释字符 || 检查是否包含 SQ L注入敏感字符
|
}
|
||||||
return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
|
|
||||||
|
/**
|
||||||
|
* 检查参数是否存在 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