当前位置:网站首页>AntiSamy:防 XSS 攻击的一种解决方案使用教程
AntiSamy:防 XSS 攻击的一种解决方案使用教程
2022-07-07 16:19:00 【华仔仔coding】
AntiSamy:防 XSS 攻击的一种解决方案使用教程
1. XSS 介绍
XSS 是跨站脚本攻击(Cross Site Scripting) 的简称,为不和 CSS(Cascading Style Sheets) 混淆,故将跨站脚本攻击缩写为 XSS. XSS 是指恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。有点类似于 SQL 注入。当网站攻击者发现这个漏洞,并攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和 cookie 等各种内容。
XSS 攻击分为两种类型:
- 持久型:XSS 攻击代码被存储到服务器的数据库中,隐秘性很高。例如,当攻击者在评论或留言板注入 XSS 攻击代码,而帖子或博客被服务器存储下来,帖子的评论或留言板自然也就被持久化到服务器的数据库中,这里面就包含了 XSS 攻击代码。当其他用户浏览这个帖子的时候,XSS 攻击代码便开始在用户的浏览器中解析并执行。
- 反射型:反射型 XSS 又称为非持久型 XSS,这种攻击方式具有一次性的特点。例如,攻击者将包含 XSS 代码的恶意链接发送给用户,当用户访问链接时,服务器收到用户请求并进行处理,再将包含 XSS 代码的数据返回给用户的浏览器,那么用户浏览器解析包含 XSS 代码的数据时,就会触发 XSS 漏洞。
- DOM 型:区别于以上两种类型,DOM 型 XSS 攻击不经过服务器,它是由攻击者直接构造一个包含 XSS 攻击代码的 URL,然后让目标用户去访问这个 URL,用户的浏览器在处理这个响应的时候,DOM 型对象就会处理 XSS 代码,触发 XSS 漏洞。
2. AntiSamy 介绍
因此为了避免这个漏洞给网站的用户带来的危害,OWASP 组织开源了一个叫做 AntiSamy 的项目,帮助我们的网站防御 XSS 攻击。它通过对用户输入的 HTML / CSS / JavaScript 等内容进行检验和清理,确保输入符合应用规范。AntiSamy 被广泛应用于 Web 服务对存储型和反射型 XSS 的防御中。
官方给出的关于 AntiSamy 的介绍是这样的:
AntiSamy 是一个 API 或 库 ,可以帮助我们开发者确保客户端不会在他们提供的 HTML 中提供恶意的代码,这些 HTML 用于保存在服务器上的配置文件、注释等。关于 web 应用程序的术语“恶意代码”通常指“JavaScript”。大多数情况下,CSS 只有在调用 JavaScript 时才被认为是恶意的。然而,在许多情况下,“正常的” HTML 和 CSS 可以被恶意使用。
3. AntiSamy 使用
3.1 导入依赖
AntiSamy 的 maven 坐标:
<dependency>
<groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>1.6.2</version>
</dependency>
3.2 选择策略文件
AntiSamy 预定义了一些策略文件,这些策略文件它们代表了允许用户提供 HTML (可能还有CSS) 格式化信息的典型应用场景,我们可以根据自己的应用场景选择合适的策略文件。具体的策略文件有以下几种:
1、antisamy-slashdot.xml
- Slashdot 是一个技术新闻网站,它允许用户匿名回复非常有限的 HTML 标记的新闻帖子。现在,Slashdot 不仅是最酷的网站之一,它也是一个受到许多不同成功攻击的网站。
- Slashdot 的规则相当严格:用户只能提交以下
<b>, <u>, <i>, <a>, <blockquote>
这些 HTML 标记,不能提交 CSS. - 因此,antisamy-slashdot.xml 文件支持类似的功能,所有直接对字体、颜色或重点进行操作的文本格式标记都是允许的,但是不允许 CSS 和 JavaScript 标记出现。
2、antisamy-ebay.xml
- eBay 是世界上最受欢迎的在线拍卖网站,它是一个公共站点,因此任何人都可以发布包含丰富 HTML 内容的清单。考虑到 eBay 作为一个有吸引力的目标,它受到一些复杂的 XSS 攻击并不奇怪。清单被允许包含比 Slashdot 更丰富的内容——所以它的攻击面相当大。
- 因此,antisamy-ebay.xml 策略文件提供的策略是支持丰富的 HTML 标记,但是不支持 CSS 标记 和 JavaScript 标记。
3、antisamy-myspace.xml
- MySpace 是一个曾经非常受欢迎的社交网站,用户可以提交几乎所有他们想要的 HTML 和CSS ——只要不包含 JavaScript. MySpace 使用一个单词黑名单来验证用户的 HTML,这就是为什么他们会受到臭名昭著的 Samy 蠕虫的攻击。Samy 蠕虫使用碎片攻击和一个应该被列入黑名单的词(eval)——是这个项目的灵感来源。
- 因此,antisamy-myspace.xml 策略文件提供的策略是支持非常丰富的 HTML 和 CSS 标记,但是不支持 JavaScript 标记。
4、antisamy-anythinggoes.xml
- 如果想允许每一个有效的 HTML 和 CSS 元素(但是不允许 JavaScript 或明显的 CSS 相关的钓鱼攻击),你可以使用这个策略文件。它包含每个元素的基本规则,所以在使用定制其他策略文件时,可以将它用作知识库。
5、antisamy-tinymce.xml
- 只允许文本格式通过,相对比较安全。
6、antisamy.xml
- 默认规则,允许大部分 HTML 标记,不允许 JavaScript 标记出现。
3.3 SpringBoot 整合 AntiSamy 使用
工程的目录结构如下:
第一步,创建 maven 工程 antiSamy_demo 并配置 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hzz</groupId>
<artifactId>antiSamy_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
第二步,创建 application.yml 文件
server:
port: 9000
第三步,创建策略文件 /resources/antisamy-slashdot.xml,策略文件可以直接从 antisamy jar 包下复制
第四步,创建实体类 User
package com.hzz.entity;
import lombok.Data;
@Data
public class User {
private int id;
private String name;
private int age;
}
第五步,创建 UserController
package com.hzz.controller;
import com.hzz.entity.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/save")
public String save(User user){
System.out.println("UserController save.... " + user);
return user.getName();
}
}
第六步,创建 /resources/static/index.html 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" action="/user/save">
id:<input type="text" name="id"><br>
name:<input type="text" name="name"><br>
age:<input type="text" name="age"><br>
<input type="submit" value="submit">
</form>
</body>
</html>
第七步,创建过滤器,用于过滤所有提交到服务器的请求参数
package com.hzz.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
//过滤所有提交到服务器的请求参数
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
//传入重写后的Request
filterChain.doFilter(new XssRequestWrapper(request), servletResponse);
}
}
过滤器 XssFilter 并没有直接进行请求参数的过滤清理,而是直接放行。其实,过滤清理的工作是在另外一个类 XssRequestWrapper 中进行的,当上面的过滤器放行时需要调用filterChain.doFilter() 方法,此方法需要传入请求 request 对象,此时我们可以将当前的 request 对象进行包装,而 XssRequestWrapper 就是 request 对象的包装类,在过滤器放行时会自动调用包装类的 getParameterValues 方法,我们可以在包装类的 getParameterValues 方法中进行统一的请求参数过滤清理。
XssRequestWrapper 包装类实现如下
package com.hzz.filter;
import org.owasp.validator.html.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.UnsupportedEncodingException;
public class XssRequestWrapper extends HttpServletRequestWrapper {
/** * 策略文件:需要将要使用的策略文件放到项目资源文件路径 */
private static String antiSamyPath = XssRequestWrapper.class.getClassLoader()
.getResource( "antisamy-ebay.xml").getFile();
public static Policy policy = null;
static {
//指定策略文件
try {
policy = Policy.getInstance(java.net.URLDecoder.decode(antiSamyPath, "utf-8")); //我的项目路径带有中文,需要转码,否则会报错,如果你的路径都是英文则忽略转码过程
} catch (PolicyException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/** * Antisamy 过滤数据 * @param taintedHTML 需要进行过滤的数据 * @Return 返回过滤后的数据 */
private String xssClean(String taintedHTML) {
try {
//使用AntiSamy 进行过滤
AntiSamy antiSamy = new AntiSamy();
CleanResults cr = antiSamy.scan(taintedHTML, policy);
taintedHTML = cr.getCleanHTML();
} catch (ScanException e) {
e.printStackTrace();
} catch (PolicyException e) {
e.printStackTrace();
}
return taintedHTML;
}
public XssRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) {
return null;
}
int len = values.length;
String[] newArray = new String[len];
for (int j = 0; j < len; j++) {
System.out.println("Antisamy 过滤清理,清理之前的参数值:"+values[j]);
//过滤清理
newArray[j] = xssClean(values[j]);
System.out.println("Antisamy 过滤清理,清理之后的参数值:"+newArray[j]);
}
return newArray;
}
}
第八步,为了使上面定义的过滤器生效,需要创建配置类,用于初始化过滤器对象
package com.hzz.config;
import com.hzz.filter.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//配置跨站攻击过滤器
@Configuration
public class AntiSamyConfiguration {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
第九步,创建启动类并启动项目,访问网站首页地址 http://localhost:9000/index.html
package com.hzz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AntiSamyApp {
public static void main(String[] args) {
SpringApplication.run(AntiSamyApp.class, args);
}
}
第十步,输入测试数据,并观察后台打印结果
从上图可以看到,测试的 XSS 攻击代码直接被清理掉了,服务器返回给浏览器的结果中没有 XSS 代码,不会被浏览器执行,成功避免了 XSS 攻击。
升级一下:
之前,我们在进行请求参数过滤时只是在包装类的 getParameterValues 方法中进行了处理,真实项目中可能用户提交的数据在请求头中,也可能用户提交的是 json 数据,所以如果考虑所有情况,我们可以在包装类中的多个方法中都进行清理处理即可,在 XssRequestWrapper 实现类中新增以下几个方法:
@Override
public String getParameter(String paramString) {
String str = super.getParameter(paramString);
if (str == null) {
return null;
}
System.out.println("Antisamy 过滤清理,清理之前的参数值:"+str);
//过滤清理
str = xssClean(str);
System.out.println("Antisamy 过滤清理,清理之后的参数值:"+str);
return str;
}
@Override
public String getHeader(String paramString) {
String str = super.getHeader(paramString);
if (str == null) {
return null;
}
System.out.println("Antisamy 过滤清理,清理之前的参数值:"+str);
//过滤清理
str = xssClean(str);
System.out.println("Antisamy 过滤清理,清理之后的参数值:"+str);
return str;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> requestMap = super.getParameterMap();
for (Map.Entry<String, String[]> me : requestMap.entrySet()) {
String[] values = me.getValue();
for (int i = 0; i < values.length; i++) {
System.out.println("Antisamy 过滤清理,清理之前的参数值:"+values[i]);
//过滤清理
values[i] = xssClean(values[i]);
System.out.println("Antisamy 过滤清理,清理之后的参数值:"+values[i]);
}
}
return requestMap;
}
边栏推荐
- zdog. JS rocket turn animation JS special effects
- 自动化测试:Robot FrameWork框架大家都想知道的实用技巧
- 保证接口数据安全的10种方案
- What skills can you master to be a "master tester" when doing software testing?
- Unlike the relatively short-lived industrial chain of consumer Internet, the industrial chain of industrial Internet is quite long
- Download, installation and development environment construction of "harmonyos" deveco
- Easy to understand [linear regression of machine learning]
- 小程序中实现付款功能
- [OKR target management] case analysis
- cf:C. Factorials and Powers of Two【dp + 排序 + 选不选板子 + 选若干个数等于已知和的最少数】
猜你喜欢
Do you really understand sticky bag and half bag? 3 minutes to understand it
Native JS verification code
Test for 3 months, successful entry "byte", my interview experience summary
讨论 | AR 应用落地前,要做好哪些准备?
通过 Play Integrity API 的 nonce 字段提高应用安全性
Backup Alibaba cloud instance OSS browser
带动画的列表选中js特效
手撕Nacos源码(先撕客户端源码)
Machine vision (1) - Overview
Improve application security through nonce field of play integrity API
随机推荐
[principles and technologies of network attack and Defense] Chapter 3: network reconnaissance technology
Win11C盘满了怎么清理?Win11清理C盘的方法
socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现
SD_DATA_RECEIVE_SHIFT_REGISTER
数学分析_笔记_第11章:Fourier级数
Chapter 2 build CRM project development environment (database design)
Wireshark分析抓包数据*.cap
Chapter 1 Introduction to CRM core business
Is it safe to open an online futures account now? How many regular futures companies are there in China?
Self made dataset in pytoch for dataset rewriting
Import requirements in batches during Yolo training Txt
Based on pytorch, we use CNN to classify our own data sets
Test for 3 months, successful entry "byte", my interview experience summary
[OKR target management] case analysis
AI 击败了人类,设计了更好的经济机制
[trusted computing] Lesson 12: TPM authorization and conversation
Cartoon | who is the first ide in the universe?
【demo】循环队列及条件锁实现goroutine间的通信
物联网OTA技术介绍
Yearning-SQL审核平台