目录
XSS意思是跨站脚本攻击,英文全称Cross Site Scripting,为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。
1、XSS危害(跨站脚本攻击)
XSS(跨站脚本攻击)的危害包括:
1. 窃取用户信息:攻击者可以利用XSS漏洞来窃取用户的敏感信息,如用户名、密码、银行账号等。
2. 控制用户会话:攻击者可以利用XSS漏洞来劫持用户的会话,从而实施恶意操作,如发送恶意请求、修改用户设置等。
3. 恶意重定向:攻击者可以利用XSS漏洞来将用户重定向到恶意网站,从而导致用户受到钓鱼攻击或安装恶意软件。
4. 破坏网站功能:攻击者可以利用XSS漏洞来篡改网站内容,破坏网站功能,甚至导致网站崩溃。
5. 影响搜索引擎排名:如果网站受到XSS攻击,搜索引擎可能会将其标记为不安全,从而影响网站的排名和信誉。
总的来说,XSS攻击可能会给用户和网站带来严重的安全风险和经济损失。因此,开发人员和网站管理员应该及时发现和修复XSS漏洞,以保护用户和网站的安全。
2、XSS攻击方式
XSS(跨站脚本攻击)是一种利用Web应用程序的漏洞,向页面注入恶意脚本,从而在用户的浏览器中执行恶意代码的攻击方式。XSS攻击的方式主要包括以下几种:
1. 存储型XSS攻击:攻击者将恶意脚本存储在Web应用程序的数据库中,当用户访问包含恶意脚本的页面时,恶意脚本会从数据库中加载并在用户的浏览器中执行。
2. 反射型XSS攻击:攻击者将恶意脚本作为参数附加到URL中,当用户点击包含恶意脚本的链接时,恶意脚本会被发送到服务器并在用户的浏览器中执行。
3. DOM型XSS攻击:攻击者利用前端JavaScript动态生成页面的特性,通过修改页面的DOM结构来执行恶意脚本。
攻击者通常利用XSS攻击来窃取用户的敏感信息、劫持用户的会话、破坏网站功能等。为了防范XSS攻击,开发人员需要对输入的数据进行严格的过滤和转义,避免将未经处理的用户输入直接输出到页面上。同时,网站管理员也需要定期对网站进行安全审计,及时发现和修复XSS漏洞。
3、实现抵御XSS攻击
首先我们要创建一个执行转义的封装类XssHttpServletRequestWrapper,这个类继承HttpServletRequestWrapper父类。 在这个类中我们需要把获取请求头和请求体数据的方法都要重写,返回的是经过XSS转义后的数据。
需要用到hutool工具包,引入依赖。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.0</version>
</dependency>
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.json.JSONUtil;
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.LinkedHashMap;
import java.util.Map;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (!StrUtil.hasEmpty(value)) {
// 清除所有HTML标签,但是保留标签内的内容,达到转义的效果
value = HtmlUtil.cleanHtmlTag(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null) {
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!StrUtil.hasEmpty(value)) {
value = HtmlUtil.cleanHtmlTag(value);
}
values[i] = value;
}
}
return values;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameters = super.getParameterMap();
LinkedHashMap<String, String[]> map = new LinkedHashMap();
if (parameters != null) {
for (String key : parameters.keySet()) {
String[] values = parameters.get(key);
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!StrUtil.hasEmpty(value)) {
value = HtmlUtil.cleanHtmlTag(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.cleanHtmlTag(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<String, Object> map = JSONUtil.parseObj(body.toString());
Map<String, Object> result = new LinkedHashMap<>();
for (String key : map.keySet()) {
Object val = map.get(key);
if (val instanceof String) {
if (!StrUtil.hasEmpty(val.toString())) {
result.put(key, HtmlUtil.cleanHtmlTag(val.toString()));
}
} else {
result.put(key, val);
}
}
String json = JSONUtil.toJsonStr(result);
ByteArrayInputStream bain = new ByteArrayInputStream(json.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) {
}
};
}
}
接下来我们要创建一个Filter类XssFilter,拦截所有的HTTP请求,然后调用上面创建的XssHttpServletRequestWrapper类,这样就能按照我们设定的方式获取请求中的数据了。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper(request);
filterChain.doFilter(wrapper, servletResponse);
}
@Override
public void destroy() {
}
}