Commit 4fff1fb2 authored by zengtianlai3's avatar zengtianlai3

2.1.1 跨站脚本:存储型XSS

parent 6f12179b
......@@ -29,7 +29,6 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
response.setHeader("Set-Cookie","HttpOnly");
return true;
}
}
\ No newline at end of file
package iot.sixiang.license.xss;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
/**
* @Author m33
* @Date 2022/6/29 13:59
* @Description
*/
@Configuration
@Slf4j
public class XSSFilterConfig {
@Bean
@DependsOn("xssFilter")
public FilterRegistrationBean filterRegistrationBean() {
log.info("===================filterRegistrationBean");
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("xssFilter");
return registration;
}
}
......@@ -7,6 +7,7 @@ import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
......@@ -25,16 +26,18 @@ public class XssFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(XssFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
public void init(FilterConfig filterConfig) {
LOGGER.info("==============> 进入init XssFilter");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(req);
LOGGER.info("========>进入XSS过滤器");
chain.doFilter(xssRequest, response);
chain.doFilter(xssRequest, resp);
LOGGER.info("=========>过滤器XSS执行完");
}
......
package iot.sixiang.license.xss;
import com.alibaba.fastjson.JSONObject;
import iot.sixiang.license.consts.ResultCode;
import iot.sixiang.license.handler.IotLicenseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.owasp.esapi.ESAPI;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.*;
......@@ -13,12 +23,107 @@ import static java.util.regex.Pattern.*;
* @Date 2022/7/4 11:24
* @Description
*/
@Slf4j
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
/**
* post请求体
*/
private byte[] body;
/**
* 是否是文件上传
*/
private boolean fileUpload = false;
/**
* sql注入正则
*/
private static String badStrReg =
"\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) throws IOException {
super(servletRequest);
String sessionStream = getBodyString(servletRequest);
body = sessionStream.getBytes(StandardCharsets.UTF_8);
}
private String getBodyString(HttpServletRequest httpservletrequest) throws IOException {
StringBuilder sb = new StringBuilder();
InputStream ins = httpservletrequest.getInputStream();
boolean isMultipartContent = ServletFileUpload.isMultipartContent(httpservletrequest);
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(httpservletrequest.getSession().getServletContext());
boolean isMultipart = commonsMultipartResolver.isMultipart(httpservletrequest);
if (isMultipartContent || isMultipart) {
fileUpload = true;
}
try (BufferedReader isr = new BufferedReader(new InputStreamReader(ins, StandardCharsets.UTF_8));) {
String line = "";
while ((line = isr.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
throw e;
}
return sb.toString();
}
/**
* 过滤请求体 json 格式的
*
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
// 非文件上传进行过滤
if (!fileUpload) {
// 获取body中的请求参数
JSONObject json = JSONObject.parseObject(new String(body));
// 校验并过滤xss攻击和sql注入
for (String k : json.keySet()) {
cleanSQLInject(cleanXSS(json.getString(k)));
}
}
// 将请求体参数流转 -- 流读取一次就会消失,所以我们事先读取之后就存在byte数组里边方便流转
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
log.debug("setReadListener");
}
};
}
/**
* 过滤sql注入 -- 需要增加通配,过滤大小写组合
*
* @param src 单个参数值
* @return
*/
public String cleanSQLInject(String src) {
// 非法sql注入正则
Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE);
if (sqlPattern.matcher(src.toUpperCase()).find()) {
log.error("sql注入检查:输入信息存在SQL攻击!");
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), "sql注入检查:参数含有非法攻击字符,已禁止继续访问!!");
}
return src;
}
@Override
......@@ -37,7 +142,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
cleanSQLInject(values[i]);
encodedValues[i] = cleanXSS(values[i]);
}
......@@ -57,6 +162,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
}
cleanSQLInject(value);
return cleanXSS(value);
}
......@@ -74,25 +181,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
}
// private String cleanXSS(String value) {
//
// //You'll need to remove the spaces from the html entities below
//
// value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
//
// value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
//
// value = value.replaceAll("'", "& #39;");
//
// value = value.replaceAll("eval\\((.*)\\)", "");
//
// value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
//
// value = value.replaceAll("script", "");
//
// return value;
//
// }
private String cleanXSS(String value) {
if (value != null) {
......@@ -105,8 +193,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
//避免src形式的表达式
//scriptPattern = compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", CASE_INSENSITIVE | MULTILINE | DOTALL);
//value = scriptPattern.matcher(value).replaceAll("");
//scriptPattern = compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", CASE_INSENSITIVE | MULTILINE | DOTALL);
//value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
......@@ -143,6 +231,9 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
scriptPattern = Pattern.compile("on.*(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
if (value.length() == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), "参数含有非法攻击字符,已禁止继续访问!!");
}
}
return value;
}
......
......@@ -304,9 +304,9 @@ Encryptor.KDF.PRF=HmacSHA256
HttpUtilities.UploadDir=C:\\ESAPI\\testUpload
HttpUtilities.UploadTempDir=C:\\temp
# Force flags on cookies, if you use HttpUtilities to set cookies
HttpUtilities.ForceHttpOnlySession=false
#HttpUtilities.ForceHttpOnlySession=false
HttpUtilities.ForceSecureSession=false
HttpUtilities.ForceHttpOnlyCookies=true
#HttpUtilities.ForceHttpOnlyCookies=true
HttpUtilities.ForceSecureCookies=true
# Maximum size of HTTP header key--the validator regex may have additional values.
HttpUtilities.MaxHeaderNameSize=256
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment