XSS跨站脚本攻击
什么是XXS?
- XSS全称跨站脚本(Cross Site Scripting),为了不和CSS混淆,故称为XSS.
- XSS攻击是一种注册型攻击,攻击者在可信的网页嵌入恶意代码,用户访问可信网站除法XSS而被攻击。
XSS的攻击方式
- 反射型:发出请求时,XSS代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS随响应内容一起返回给浏览器,最后浏览器解析执行XSS代码,这个过程就像一次发射,所以叫反射型XSS。
- 存储型: 存储型XSS和反射型的XSS差别就在于,存储型的XSS提交的代码会存储在服务器端(数据库,内存,文件系统等),下次请求目标页面时不用再提交XSS代码。
XSS会造成那些危害?
攻击者通过Web应用程序发送恶意代码,一般以浏览器脚本的形式发送给不同的终端用户。当一个Web程序的用户输入点没有进行校验和编码,将很容易的导致XSS。
- 网络钓鱼,包括获取各类用户账号;
- 窃取用户cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网>* 站执行操作;
- 劫持用户(浏览器)会话,从而执行任意操作,例如非法转账、强制发表日志、电子邮件等;
- 强制弹出广告页面、刷流量等;
- 网页挂马;
- 进行恶意操作,如任意篡改页面信息、删除文章等;
- 进行大量的客户端攻击,如ddos等;
- 获取客户端信息,如用户的浏览历史、真实ip、开放端口等;
- 控制受害者机器向其他网站发起攻击;
- 结合其他漏洞,如csrf,实施进一步危害;
- 提升用户权限,包括进一步渗透网站;
- 传播跨站脚本蠕虫等
XSS常见出现漏洞的地方
- 数据交互的地方
- get、post、cookies、headers
- 反馈与浏览
- 富文本编辑器
- 各类标签插入和自定义
- 数据输出的地方
- 用户资料
- 关键词、标签、说明
- 文件上传
XSS的防御
使用XSS Filter
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
@WebFilter(filterName = "xss",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 {
// 程序防止XSS攻击原理
// 1. 使用过滤器拦截所有参数
HttpServletRequest request =(HttpServletRequest) servletRequest;
// 2.重写getParameter方法
XssHttpServletRequestWrapper XssHttpServletRequestWrapper = new XssHttpServletRequestWrapper(request);
// 放行程序,继续往下执行
filterChain.doFilter(XssHttpServletRequestWrapper, servletResponse);
}
@Override
public void destroy() {
}
}
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if (value != null) {
value = StringEscapeUtils.escapeHtml(value);
}
return value;
}
@Override
public String getParameter(String name){
// 获取之前的参数
String value = super.getParameter(name);
if(!StringUtils.isEmpty(value)) {
// 使用(StringEscapeUtils.escapeHtml(name)转换特殊参数
value = StringEscapeUtils.escapeHtml(value);
}
return value;
}
}
- SpringBoot启动加上@ServletComponentScan
- 使用@RequestParam 需要重写getParameterValues方法
@Override
public String[] getParameterValues(String name){
// 获取之前的参数
String[] values = super.getParameterValues(name);
if(values!=null) {
for (int i = 0; i < values.length; i++) {
values[i] = StringEscapeUtils.escapeHtml(values[i]);
}
}
return values;
}