Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
0791df7b71
|
|
@ -68,11 +68,9 @@ public class ParamSecureHandler implements AsyncHandlerInterceptor {
|
||||||
// 过滤文件上传功能-只对参数进行校验
|
// 过滤文件上传功能-只对参数进行校验
|
||||||
if (isFileUpload(request)) {
|
if (isFileUpload(request)) {
|
||||||
String params = request.getParameter("params");
|
String params = request.getParameter("params");
|
||||||
// boolean flag = XssCheck.xssCleanNew(params);
|
|
||||||
XssCheck.XssCheckResult xssCheckResult = XssCheck.xssCheckWithResult(null, params, null, null);
|
XssCheck.XssCheckResult xssCheckResult = XssCheck.xssCheckWithResult(null, params, null, null);
|
||||||
if(!xssCheckResult.isSafe()){
|
if(!xssCheckResult.isSafe()){
|
||||||
Map<String, Object> map = new HashMap<>(16);
|
Map<String, Object> map = new HashMap<>(16);
|
||||||
// returnJson(response, "输入值非法", 500,null);
|
|
||||||
List<XssCheck.IllegalParameter> illegalParameters = xssCheckResult.getIllegalParameters();
|
List<XssCheck.IllegalParameter> illegalParameters = xssCheckResult.getIllegalParameters();
|
||||||
if(CollectionUtils.isNotEmpty(illegalParameters)){
|
if(CollectionUtils.isNotEmpty(illegalParameters)){
|
||||||
log.error("非法参数{}",illegalParameters);
|
log.error("非法参数{}",illegalParameters);
|
||||||
|
|
@ -87,19 +85,15 @@ public class ParamSecureHandler implements AsyncHandlerInterceptor {
|
||||||
}
|
}
|
||||||
XssRequestWrapper requestWrapper = new XssRequestWrapper(request);
|
XssRequestWrapper requestWrapper = new XssRequestWrapper(request);
|
||||||
|
|
||||||
// System.err.println(JSON.toJSONString(request.getParameterMap()));
|
|
||||||
/**
|
/**
|
||||||
* 校验参数是否合法
|
* 校验参数是否合法
|
||||||
*/
|
*/
|
||||||
if (!requestWrapper.isChecked()) {
|
if (!requestWrapper.isChecked()) {
|
||||||
/*log.error("输入值非法: queryString={}, body={}",
|
|
||||||
StringUtils.defaultString(requestWrapper.getQueryString(), "null"),
|
|
||||||
StringUtils.defaultString(requestWrapper.getReaderParam(), "null"));*/
|
|
||||||
|
|
||||||
Map<String, Object> map = new HashMap<>(16);
|
Map<String, Object> map = new HashMap<>(16);
|
||||||
List<XssRequestWrapper.IllegalParameter> illegalParameters = requestWrapper.getIllegalParameters();
|
List<XssRequestWrapper.IllegalParameter> illegalParameters = requestWrapper.getIllegalParameters();
|
||||||
if(CollectionUtils.isNotEmpty(illegalParameters)){
|
if(CollectionUtils.isNotEmpty(illegalParameters)){
|
||||||
log.error("非法参数{}",illegalParameters);
|
// log.error("非法参数{}",illegalParameters);
|
||||||
XssRequestWrapper.IllegalParameter illegalParameter = illegalParameters.get(0);
|
XssRequestWrapper.IllegalParameter illegalParameter = illegalParameters.get(0);
|
||||||
map.put("paramName",illegalParameter.getParamName().replace("REQUEST_BODY.",""));
|
map.put("paramName",illegalParameter.getParamName().replace("REQUEST_BODY.",""));
|
||||||
map.put("originalValue",illegalParameter.getOriginalValue());
|
map.put("originalValue",illegalParameter.getOriginalValue());
|
||||||
|
|
@ -108,7 +102,6 @@ public class ParamSecureHandler implements AsyncHandlerInterceptor {
|
||||||
returnJson(response, "输入值非法", 500,map);
|
returnJson(response, "输入值非法", 500,map);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// System.err.println(JSON.toJSONString(request.getParameterMap()));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有跳转路径参数,保留传入下个界面
|
* 获取所有跳转路径参数,保留传入下个界面
|
||||||
|
|
@ -123,7 +116,7 @@ public class ParamSecureHandler implements AsyncHandlerInterceptor {
|
||||||
/**
|
/**
|
||||||
* 检查数据流参数
|
* 检查数据流参数
|
||||||
*/
|
*/
|
||||||
String readerParam = requestWrapper.getReaderParam();
|
/*String readerParam = requestWrapper.getReaderParam();
|
||||||
// 判断是否是文件上传,是不对流参数进行验证
|
// 判断是否是文件上传,是不对流参数进行验证
|
||||||
String uplFile = "/upload", upImage = "/uploadFiles",path="/";
|
String uplFile = "/upload", upImage = "/uploadFiles",path="/";
|
||||||
if (!requestUrl.contains(uplFile) && !requestUrl.contains(upImage) && !requestUrl.contains(path)) {
|
if (!requestUrl.contains(uplFile) && !requestUrl.contains(upImage) && !requestUrl.contains(path)) {
|
||||||
|
|
@ -132,7 +125,7 @@ public class ParamSecureHandler implements AsyncHandlerInterceptor {
|
||||||
returnJson(response, "不安全参数", 500,null);
|
returnJson(response, "不安全参数", 500,null);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,23 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
// 预编译所有正则表达式模式以提高性能
|
// 预编译所有正则表达式模式以提高性能
|
||||||
private static final List<Pattern> XSS_PATTERNS = new ArrayList<>();
|
private static final List<Pattern> XSS_PATTERNS = new ArrayList<>();
|
||||||
|
|
||||||
|
// 需要忽略特殊字符校验的URL路径
|
||||||
|
private static final Set<String> IGNORE_SPECIAL_CHARS_URLS = new HashSet<>();
|
||||||
|
|
||||||
|
// 需要忽略的特殊字符模式(在修改密码时需要忽略的)
|
||||||
|
private static final List<Pattern> IGNORE_SPECIAL_PATTERNS = new ArrayList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
// 初始化忽略校验的URL路径
|
||||||
|
IGNORE_SPECIAL_CHARS_URLS.add("/smartArchives/system/user/resetPwd");
|
||||||
|
IGNORE_SPECIAL_CHARS_URLS.add("/smartArchives/system/user/profile/updatePwd");
|
||||||
|
// 可以根据需要添加更多修改密码的URL
|
||||||
|
|
||||||
|
// 初始化需要忽略的特殊字符模式
|
||||||
|
IGNORE_SPECIAL_PATTERNS.add(Pattern.compile("@.*", Pattern.CASE_INSENSITIVE)); // @符号
|
||||||
|
IGNORE_SPECIAL_PATTERNS.add(Pattern.compile("!.*", Pattern.CASE_INSENSITIVE)); // 感叹号
|
||||||
|
IGNORE_SPECIAL_PATTERNS.add(Pattern.compile("%", Pattern.CASE_INSENSITIVE)); // %
|
||||||
|
|
||||||
// 初始化所有XSS模式
|
// 初始化所有XSS模式
|
||||||
XSS_PATTERNS.add(Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE));
|
XSS_PATTERNS.add(Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE));
|
||||||
XSS_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*'(.*?)'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
XSS_PATTERNS.add(Pattern.compile("src[\r\n]*=[\r\n]*'(.*?)'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
|
@ -73,10 +89,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
XSS_PATTERNS.add(Pattern.compile("%5b", Pattern.CASE_INSENSITIVE)); // [ 的URL编码
|
XSS_PATTERNS.add(Pattern.compile("%5b", Pattern.CASE_INSENSITIVE)); // [ 的URL编码
|
||||||
XSS_PATTERNS.add(Pattern.compile("%5d", Pattern.CASE_INSENSITIVE)); // ] 的URL编码
|
XSS_PATTERNS.add(Pattern.compile("%5d", Pattern.CASE_INSENSITIVE)); // ] 的URL编码
|
||||||
|
|
||||||
// 其他特殊字符
|
// 注意:@、!、% 这三个模式被移到 IGNORE_SPECIAL_PATTERNS 中,不在 XSS_PATTERNS 中
|
||||||
XSS_PATTERNS.add(Pattern.compile("@.*", Pattern.CASE_INSENSITIVE)); // @符号
|
|
||||||
XSS_PATTERNS.add(Pattern.compile("!.*", Pattern.CASE_INSENSITIVE)); // 感叹号
|
|
||||||
XSS_PATTERNS.add(Pattern.compile("%", Pattern.CASE_INSENSITIVE)); // %
|
|
||||||
|
|
||||||
// 十六进制编码
|
// 十六进制编码
|
||||||
XSS_PATTERNS.add(Pattern.compile("\\\\x3c", Pattern.CASE_INSENSITIVE)); // < 的十六进制
|
XSS_PATTERNS.add(Pattern.compile("\\\\x3c", Pattern.CASE_INSENSITIVE)); // < 的十六进制
|
||||||
|
|
@ -271,11 +284,19 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
String cleanedValue = value;
|
String cleanedValue = value;
|
||||||
// 使用预编译的模式
|
|
||||||
|
// 首先使用主要XSS模式进行清理
|
||||||
for (Pattern pattern : XSS_PATTERNS) {
|
for (Pattern pattern : XSS_PATTERNS) {
|
||||||
cleanedValue = pattern.matcher(cleanedValue).replaceAll("");
|
cleanedValue = pattern.matcher(cleanedValue).replaceAll("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果不是修改密码请求,才对特殊字符进行清理
|
||||||
|
if (!isPasswordUpdateRequest()) {
|
||||||
|
for (Pattern pattern : IGNORE_SPECIAL_PATTERNS) {
|
||||||
|
cleanedValue = pattern.matcher(cleanedValue).replaceAll("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 如果值被修改,记录非法参数
|
// 如果值被修改,记录非法参数
|
||||||
if (!cleanedValue.equals(value)) {
|
if (!cleanedValue.equals(value)) {
|
||||||
recordIllegalParameter(paramName, value, cleanedValue, "XSS_ATTACK");
|
recordIllegalParameter(paramName, value, cleanedValue, "XSS_ATTACK");
|
||||||
|
|
@ -295,15 +316,42 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
return isJsonSafe(paramName, value);
|
return isJsonSafe(paramName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用预编译的模式进行检查
|
boolean isSafe = true;
|
||||||
|
|
||||||
|
// 使用预编译的模式进行检查(主要XSS模式)
|
||||||
for (Pattern pattern : XSS_PATTERNS) {
|
for (Pattern pattern : XSS_PATTERNS) {
|
||||||
if (match(pattern, value)) {
|
if (match(pattern, value)) {
|
||||||
// 发现XSS攻击,记录非法参数
|
// 发现XSS攻击,记录非法参数
|
||||||
recordIllegalParameter(paramName, value, null, "XSS_PATTERN_" + pattern.pattern());
|
recordIllegalParameter(paramName, value, null, "XSS_PATTERN_" + pattern.pattern());
|
||||||
return false;
|
isSafe = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true; // 安全
|
|
||||||
|
// 如果不是修改密码请求,才对特殊字符进行检查
|
||||||
|
if (!isPasswordUpdateRequest()) {
|
||||||
|
for (Pattern pattern : IGNORE_SPECIAL_PATTERNS) {
|
||||||
|
if (match(pattern, value)) {
|
||||||
|
recordIllegalParameter(paramName, value, null, "SPECIAL_CHAR_PATTERN_" + pattern.pattern());
|
||||||
|
isSafe = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSafe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为修改密码请求
|
||||||
|
*/
|
||||||
|
private boolean isPasswordUpdateRequest() {
|
||||||
|
String requestURI = ((HttpServletRequest) getRequest()).getRequestURI();
|
||||||
|
for (String url : IGNORE_SPECIAL_CHARS_URLS) {
|
||||||
|
if (requestURI.contains(url)) {
|
||||||
|
log.debug("检测到修改密码请求,忽略特殊字符校验: {}", requestURI);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查字符串是否为JSON格式
|
// 检查字符串是否为JSON格式
|
||||||
|
|
@ -420,13 +468,25 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isSafe = true;
|
boolean isSafe = true;
|
||||||
|
|
||||||
|
// 检查主要XSS模式
|
||||||
for (Pattern pattern : XSS_PATTERNS) {
|
for (Pattern pattern : XSS_PATTERNS) {
|
||||||
if (match(pattern, value)) {
|
if (match(pattern, value)) {
|
||||||
recordIllegalParameter(paramName, value, null, "XSS_PATTERN_" + pattern.pattern());
|
recordIllegalParameter(paramName, value, null, "XSS_PATTERN_" + pattern.pattern());
|
||||||
isSafe = false;
|
isSafe = false;
|
||||||
// 继续检查其他模式,记录所有匹配的攻击模式
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果不是修改密码请求,才对特殊字符进行检查
|
||||||
|
if (!isPasswordUpdateRequest()) {
|
||||||
|
for (Pattern pattern : IGNORE_SPECIAL_PATTERNS) {
|
||||||
|
if (match(pattern, value)) {
|
||||||
|
recordIllegalParameter(paramName, value, null, "SPECIAL_CHAR_PATTERN_" + pattern.pattern());
|
||||||
|
isSafe = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return isSafe;
|
return isSafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,6 +501,11 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
* 记录非法参数信息
|
* 记录非法参数信息
|
||||||
*/
|
*/
|
||||||
private void recordIllegalParameter(String paramName, String originalValue, String cleanedValue, String attackType) {
|
private void recordIllegalParameter(String paramName, String originalValue, String cleanedValue, String attackType) {
|
||||||
|
// 如果是修改密码请求,且攻击类型是特殊字符,则不记录
|
||||||
|
if (isPasswordUpdateRequest() && attackType.startsWith("SPECIAL_CHAR_PATTERN_")) {
|
||||||
|
return; // 忽略记录特殊字符攻击
|
||||||
|
}
|
||||||
|
|
||||||
IllegalParameter illegalParam = new IllegalParameter();
|
IllegalParameter illegalParam = new IllegalParameter();
|
||||||
illegalParam.setParamName(paramName);
|
illegalParam.setParamName(paramName);
|
||||||
illegalParam.setOriginalValue(originalValue);
|
illegalParam.setOriginalValue(originalValue);
|
||||||
|
|
@ -452,11 +517,12 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
illegalParameters.add(illegalParam);
|
illegalParameters.add(illegalParam);
|
||||||
|
|
||||||
// 记录警告日志
|
// 记录警告日志(特殊字符攻击在修改密码时不记录)
|
||||||
/*log.warn("检测到XSS攻击尝试 - 参数: {}, 攻击类型: {}, 原始值: {}, 客户端IP: {}",
|
if (!(isPasswordUpdateRequest() && attackType.startsWith("SPECIAL_CHAR_PATTERN_"))) {
|
||||||
paramName, attackType,
|
log.warn("检测到安全威胁 - 参数: {}, 攻击类型: {}, 原始值: {}",
|
||||||
originalValue.length() > 100 ? originalValue.substring(0, 100) + "..." : originalValue,
|
paramName, attackType,
|
||||||
illegalParam.getClientIp());*/
|
originalValue.length() > 100 ? originalValue.substring(0, 100) + "..." : originalValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -527,6 +593,5 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
private Date detectedTime; // 检测时间
|
private Date detectedTime; // 检测时间
|
||||||
private String requestUrl; // 请求URL
|
private String requestUrl; // 请求URL
|
||||||
private String clientIp; // 客户端IP
|
private String clientIp; // 客户端IP
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue