XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是Javascript,但实际上也可以包括Java、Vbscript、ActiveX、Flash或者甚至是普通的HTML。攻击成功后, 攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和COOKIE等各种内容。 例如用户在发帖或者注册的时候,在文本框中输入,这段代码如果不经过转义处理,而直接保存到数据库。将来视图层渲染HTML的时候,把这段代码输出到页面上,那么
cn.hutool hutool-all 5.4.0三、定义请求包装类package com.example.emos.wx.config.xss;import cn.hutool.core.util.StrUtil;import cn.hutool.http.HtmlUtil;import cn.hutool.json.JSONUtil;import javax.print.DocFlavor;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.Charset;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;public class XssHttpServeletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServeletRequestWrapper(HttpServletRequest request){ super(request); } @Override public String getParameter(String name){ String value = super.getParameter(name); //获取请求中的原始数据 if(!StrUtil.hasEmpty(value)){ //数据不为空 value = HtmlUtil.filter(value); //把数据做转义,把html、script标签去掉,变成普通的文本 } return value; } /**转义数组中的数据*/ @Override public String[] getParameterValues(String name){ String[] values = super.getParameterValues(name); if(values != null){ for(int i=0;i String value = values[i]; if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } values[i] = value; } } return values; } @Override public Map getParameterMap(){ Map parameters = super.getParameterMap(); LinkedHashMap map = new LinkedHashMap(); if(parameters != null){ for(String key:parameters.keySet()){ String[] values = parameters.get(key); for(int i=0;i String value = values[i]; if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } values[i] = value; } map.put(key,values); } } return map; } @Override public String getHeader(String name) { String value = super.getHeader(name); if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } return value; } @Override public ServletInputStream getInputStream() throws IOException{ InputStream in = super.getInputStream(); InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8")); BufferedReader buffer = new BufferedReader(reader); StringBuffer body = new StringBuffer(); String line = buffer.readLine(); while (line != null){ body.append(line); line = buffer.readLine(); } buffer.close(); reader.close(); in.close(); Map map = JSONUtil.parseObj(body.toString()); Map resultMap = new LinkedHashMap<>(); for(String key : map.keySet()){ Object val = map.get(key); if(map.get(key) instanceof String){ if(!StrUtil.hasEmpty(val.toString())){ resultMap.put(key, HtmlUtil.filter(val.toString())); } }else{ resultMap.put(key, val); } } String str = JSONUtil.toJsonStr(resultMap); final ByteArrayInputStream bain = new ByteArrayInputStream(str.getBytes()); return new ServletInputStream() { @Override public int read() throws IOException { return bain.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; }}四、创建过滤器,把所有请求对象传入包装类package com.example.emos.wx.config.xss;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import java.io.IOException;@WebFilter(urlPatterns = "/*") //拦截请求的路径public class XssFilter implements Filter { public void init(FilterConfig config) throws ServletException{ } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { XssHttpServeletRequestWrapper wrapper = new XssHttpServeletRequestWrapper((HttpServletRequest) request); chain.doFilter(wrapper,response); } @Override public void destroy() { }}五、给主类添加注解给SpringBoot主类添加@ServletComponentScan注解六、测试拦截XSS脚本测试controller@RestController@RequestMapping("/test")@Api("测试Web接口")public class TestController { @PostMapping("/sayHello") @ApiOperation("最简单的测试方法") public R sayHello(@Valid @RequestBody TestSayHelloForm form){ return R.ok().put("message","Hello,"+form.getName()); }}@ApiModel@Datapublic class TestSayHelloForm { @NotBlank private String name;}在Swagger中执行sayHello()方法,向name属性传入观察返回结果
cn.hutool hutool-all 5.4.0
package com.example.emos.wx.config.xss;import cn.hutool.core.util.StrUtil;import cn.hutool.http.HtmlUtil;import cn.hutool.json.JSONUtil;import javax.print.DocFlavor;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.Charset;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;public class XssHttpServeletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServeletRequestWrapper(HttpServletRequest request){ super(request); } @Override public String getParameter(String name){ String value = super.getParameter(name); //获取请求中的原始数据 if(!StrUtil.hasEmpty(value)){ //数据不为空 value = HtmlUtil.filter(value); //把数据做转义,把html、script标签去掉,变成普通的文本 } return value; } /**转义数组中的数据*/ @Override public String[] getParameterValues(String name){ String[] values = super.getParameterValues(name); if(values != null){ for(int i=0;i String value = values[i]; if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } values[i] = value; } } return values; } @Override public Map getParameterMap(){ Map parameters = super.getParameterMap(); LinkedHashMap map = new LinkedHashMap(); if(parameters != null){ for(String key:parameters.keySet()){ String[] values = parameters.get(key); for(int i=0;i String value = values[i]; if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } values[i] = value; } map.put(key,values); } } return map; } @Override public String getHeader(String name) { String value = super.getHeader(name); if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } return value; } @Override public ServletInputStream getInputStream() throws IOException{ InputStream in = super.getInputStream(); InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8")); BufferedReader buffer = new BufferedReader(reader); StringBuffer body = new StringBuffer(); String line = buffer.readLine(); while (line != null){ body.append(line); line = buffer.readLine(); } buffer.close(); reader.close(); in.close(); Map map = JSONUtil.parseObj(body.toString()); Map resultMap = new LinkedHashMap<>(); for(String key : map.keySet()){ Object val = map.get(key); if(map.get(key) instanceof String){ if(!StrUtil.hasEmpty(val.toString())){ resultMap.put(key, HtmlUtil.filter(val.toString())); } }else{ resultMap.put(key, val); } } String str = JSONUtil.toJsonStr(resultMap); final ByteArrayInputStream bain = new ByteArrayInputStream(str.getBytes()); return new ServletInputStream() { @Override public int read() throws IOException { return bain.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; }}四、创建过滤器,把所有请求对象传入包装类
package com.example.emos.wx.config.xss;import cn.hutool.core.util.StrUtil;import cn.hutool.http.HtmlUtil;import cn.hutool.json.JSONUtil;import javax.print.DocFlavor;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.Charset;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;public class XssHttpServeletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServeletRequestWrapper(HttpServletRequest request){ super(request); } @Override public String getParameter(String name){ String value = super.getParameter(name); //获取请求中的原始数据 if(!StrUtil.hasEmpty(value)){ //数据不为空 value = HtmlUtil.filter(value); //把数据做转义,把html、script标签去掉,变成普通的文本 } return value; } /**转义数组中的数据*/ @Override public String[] getParameterValues(String name){ String[] values = super.getParameterValues(name); if(values != null){ for(int i=0;i String value = values[i]; if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } values[i] = value; } } return values; } @Override public Map getParameterMap(){ Map parameters = super.getParameterMap(); LinkedHashMap map = new LinkedHashMap(); if(parameters != null){ for(String key:parameters.keySet()){ String[] values = parameters.get(key); for(int i=0;i String value = values[i]; if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } values[i] = value; } map.put(key,values); } } return map; } @Override public String getHeader(String name) { String value = super.getHeader(name); if(!StrUtil.hasEmpty(value)){ value = HtmlUtil.filter(value); } return value; } @Override public ServletInputStream getInputStream() throws IOException{ InputStream in = super.getInputStream(); InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8")); BufferedReader buffer = new BufferedReader(reader); StringBuffer body = new StringBuffer(); String line = buffer.readLine(); while (line != null){ body.append(line); line = buffer.readLine(); } buffer.close(); reader.close(); in.close(); Map map = JSONUtil.parseObj(body.toString()); Map resultMap = new LinkedHashMap<>(); for(String key : map.keySet()){ Object val = map.get(key); if(map.get(key) instanceof String){ if(!StrUtil.hasEmpty(val.toString())){ resultMap.put(key, HtmlUtil.filter(val.toString())); } }else{ resultMap.put(key, val); } } String str = JSONUtil.toJsonStr(resultMap); final ByteArrayInputStream bain = new ByteArrayInputStream(str.getBytes()); return new ServletInputStream() { @Override public int read() throws IOException { return bain.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; }}
package com.example.emos.wx.config.xss;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import java.io.IOException;@WebFilter(urlPatterns = "/*") //拦截请求的路径public class XssFilter implements Filter { public void init(FilterConfig config) throws ServletException{ } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { XssHttpServeletRequestWrapper wrapper = new XssHttpServeletRequestWrapper((HttpServletRequest) request); chain.doFilter(wrapper,response); } @Override public void destroy() { }}五、给主类添加注解
package com.example.emos.wx.config.xss;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import java.io.IOException;@WebFilter(urlPatterns = "/*") //拦截请求的路径public class XssFilter implements Filter { public void init(FilterConfig config) throws ServletException{ } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { XssHttpServeletRequestWrapper wrapper = new XssHttpServeletRequestWrapper((HttpServletRequest) request); chain.doFilter(wrapper,response); } @Override public void destroy() { }}
给SpringBoot主类添加@ServletComponentScan注解
@ServletComponentScan
测试controller
@RestController@RequestMapping("/test")@Api("测试Web接口")public class TestController { @PostMapping("/sayHello") @ApiOperation("最简单的测试方法") public R sayHello(@Valid @RequestBody TestSayHelloForm form){ return R.ok().put("message","Hello,"+form.getName()); }}@ApiModel@Datapublic class TestSayHelloForm { @NotBlank private String name;}
在Swagger中执行sayHello()方法,向name属性传入观察返回结果