XSS 配置
This commit is contained in:
parent
de712aea1a
commit
94bd1e3b46
|
|
@ -147,6 +147,12 @@
|
||||||
<version>1.9.7</version>
|
<version>1.9.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20231013</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -70,13 +70,13 @@ public class ParamSecureHandler implements AsyncHandlerInterceptor {
|
||||||
/**
|
/**
|
||||||
* 校验参数是否合法
|
* 校验参数是否合法
|
||||||
*/
|
*/
|
||||||
/*if (!requestWrapper.isChecked()) {
|
if (!requestWrapper.isChecked()) {
|
||||||
log.error("输入值非法: queryString={}, body={}",
|
log.error("输入值非法: queryString={}, body={}",
|
||||||
StringUtils.defaultString(requestWrapper.getQueryString(), "null"),
|
StringUtils.defaultString(requestWrapper.getQueryString(), "null"),
|
||||||
StringUtils.defaultString(requestWrapper.getReaderParam(), "null"));
|
StringUtils.defaultString(requestWrapper.getReaderParam(), "null"));
|
||||||
returnJson(response, "输入值非法", 500);
|
returnJson(response, "输入值非法", 500);
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}
|
||||||
// System.err.println(JSON.toJSONString(request.getParameterMap()));
|
// System.err.println(JSON.toJSONString(request.getParameterMap()));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package com.bonus.framework.interceptor;
|
package com.bonus.framework.interceptor;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import javax.servlet.ReadListener;
|
import javax.servlet.ReadListener;
|
||||||
import javax.servlet.ServletInputStream;
|
import javax.servlet.ServletInputStream;
|
||||||
|
|
@ -195,6 +198,12 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 首先检查是否为JSON格式
|
||||||
|
if (isJsonString(value)) {
|
||||||
|
// 对JSON字符串进行特殊处理:检查值部分是否包含XSS
|
||||||
|
return isJsonSafe(value);
|
||||||
|
}
|
||||||
|
|
||||||
List<Pattern> patterns = new ArrayList<>();
|
List<Pattern> patterns = new ArrayList<>();
|
||||||
patterns.add(Pattern.compile(regex1, Pattern.CASE_INSENSITIVE));
|
patterns.add(Pattern.compile(regex1, Pattern.CASE_INSENSITIVE));
|
||||||
patterns.add(Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
patterns.add(Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
|
@ -216,6 +225,123 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
||||||
return true; // 安全
|
return true; // 安全
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查字符串是否为JSON格式
|
||||||
|
private boolean isJsonString(String str) {
|
||||||
|
try {
|
||||||
|
// 尝试解析为JSON对象
|
||||||
|
new JSONObject(str);
|
||||||
|
return true;
|
||||||
|
} catch (JSONException e1) {
|
||||||
|
try {
|
||||||
|
// 尝试解析为JSON数组
|
||||||
|
new JSONArray(str);
|
||||||
|
return true;
|
||||||
|
} catch (JSONException e2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查JSON字符串中的值是否安全
|
||||||
|
private boolean isJsonSafe(String jsonStr) {
|
||||||
|
try {
|
||||||
|
// 处理JSON对象
|
||||||
|
if (jsonStr.trim().startsWith("{")) {
|
||||||
|
JSONObject jsonObject = new JSONObject(jsonStr);
|
||||||
|
return isJsonObjectSafe(jsonObject);
|
||||||
|
}
|
||||||
|
// 处理JSON数组
|
||||||
|
else if (jsonStr.trim().startsWith("[")) {
|
||||||
|
JSONArray jsonArray = new JSONArray(jsonStr);
|
||||||
|
return isJsonArraySafe(jsonArray);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// 解析失败,回退到普通字符串检查
|
||||||
|
return xssCleanNewFallback(jsonStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归检查JSON对象的安全性
|
||||||
|
private boolean isJsonObjectSafe(JSONObject jsonObject) throws JSONException {
|
||||||
|
Iterator<String> keys = jsonObject.keys();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Object value = jsonObject.get(key);
|
||||||
|
|
||||||
|
// 检查key的安全性
|
||||||
|
if (!xssCleanNewFallback(key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查value的安全性
|
||||||
|
if (value instanceof String) {
|
||||||
|
if (!xssCleanNewFallback((String) value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (value instanceof JSONObject) {
|
||||||
|
if (!isJsonObjectSafe((JSONObject) value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (value instanceof JSONArray) {
|
||||||
|
if (!isJsonArraySafe((JSONArray) value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归检查JSON数组的安全性
|
||||||
|
private boolean isJsonArraySafe(JSONArray jsonArray) throws JSONException {
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
Object value = jsonArray.get(i);
|
||||||
|
|
||||||
|
if (value instanceof String) {
|
||||||
|
if (!xssCleanNewFallback((String) value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (value instanceof JSONObject) {
|
||||||
|
if (!isJsonObjectSafe((JSONObject) value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (value instanceof JSONArray) {
|
||||||
|
if (!isJsonArraySafe((JSONArray) value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回退到原始的模式匹配(避免递归调用)
|
||||||
|
private boolean xssCleanNewFallback(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Pattern> patterns = new ArrayList<>();
|
||||||
|
// 这里添加你的所有XSS模式...
|
||||||
|
patterns.add(Pattern.compile(regex1, Pattern.CASE_INSENSITIVE));
|
||||||
|
patterns.add(Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
patterns.add(Pattern.compile(regex3, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
patterns.add(Pattern.compile(regex4, Pattern.CASE_INSENSITIVE));
|
||||||
|
patterns.add(Pattern.compile(regex5, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
patterns.add(Pattern.compile(regex6, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
patterns.add(Pattern.compile(regex7, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
patterns.add(Pattern.compile(regex8, Pattern.CASE_INSENSITIVE));
|
||||||
|
patterns.add(Pattern.compile(regex9, Pattern.CASE_INSENSITIVE));
|
||||||
|
patterns.add(Pattern.compile(regex10, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
|
||||||
|
patterns.add(Pattern.compile(SAFE_SCRIPT_PATTERN, Pattern.CASE_INSENSITIVE));
|
||||||
|
|
||||||
|
for (Pattern pattern : patterns) {
|
||||||
|
if (match(pattern, value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行正则表达式匹配
|
* 执行正则表达式匹配
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue