当前位置:网站首页>五、品达通用权限系统__pd-tools-xxs(防跨站脚本攻击)
五、品达通用权限系统__pd-tools-xxs(防跨站脚本攻击)
2022-07-25 21:24:00 【上善若水】
一、pd-tools-xxs
pd-tools-xxs模块定位为防跨站脚本攻击(XSS),通过对用户在页面输入的HTML / CSS / JavaScript等内容进行校验和清理,确保输入内容符合应用规范,保障系统的安全。
1.1、XSS介绍
XSS:跨站脚本攻击(Cross Site Scripting),为不和CSS混淆,故将跨站脚本攻击缩写为XSS。XSS是指恶意攻击者往web页面里插入恶意Script代码,当用户浏览该页时,嵌入其中web里面的Script代码会被执行,从而达到恶意攻击用户的目的。有点类似于sql注入。
XSS攻击原理:HTML是一种超文本标记语言,通过将一些字符特殊地对待来区别文本和标记,例如,小于符号<被看作是HTML标签的开始,<title>与</title>之间的字符是页面的标题等等。当动态页面中插入的内容含有这些特殊字符时,用户浏览器会将其误认为是插入了HTML标签,当这些HTML标签引入了一段JavaScript脚本时,这些脚本程序就将会在用户浏览器中执行。所以,当这些特殊字符不能被动态页面检查或检查出现失误时,就将会产生XSS漏洞。
1.2、AnitSamy介绍
AnitSamy是OWASP的一个开源项目,通过对用户输入的 HTML / CSS / JavaScript等内容进行校验和清理,确保输入符合应用规范。AnitSamy被广泛应用于web服务对存储型和反射型XSS的防御中。AnitSamy的maven坐标:
<dependency>
<groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>1.5.7</version>
</dependency>
1.3、AnitSamy入门案例
第一步:创建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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.xbmu</groupId>
<artifactId>antiSamy_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<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.5.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
第二步:创建application.yml
server:
port: 9000
第三步:创建策略文件/resources/antisamy-test.xml,文件内容可以从antisamy的jar包中获取
注: AntiSamy对恶意代码的过滤依赖于策略文件。策略文件规定了AntiSamy对各个标签、属性的处理方法,策略文件定义的严格与否,决定了AntiSamy对XSS漏洞的防御效果。在AntiSamy的jar包中,包含了几个常用的策略文件
第四步:创建User实体类
package com.xbmu.entity;
import lombok.Data;
@Data
public class User {
private int id;
private String name;
private int age;
}
第五步:创建UserController
package com.xbmu.controller;
import com.xbmu.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.xbmu;
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);
}
}
此时我们可以启动项目进行访问,但是还没有进行参数的过滤,所以如果我们输入任意参数都可以正常传递到Controller中,这在实际项目中是非常不安全的。为了对我们输入的数据进行过滤清理,需要通过过滤器来实现。
第八步:创建过滤器,用于过滤所有提交到服务器的请求参数
package com.xbmu.filter;
import com.xbmu.wrapper.XssRequestWrapper;
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);
}
}
注意:通过上面的过滤器可以发现我们并没有在过滤器中直接进行请求参数的过滤清理,而是直接放行了,那么我们还怎么进行请求参数的过滤清理呢?其实过滤清理的工作是在另外一个类XssRequestWrapper中进行的,当上面的过滤器放行时需要调用filterChain.doFilter()方法,此方法需要传入请求Request对象,此时我们可以将当前的request对象进行包装,而XssRequestWrapper就是Request对象的包装类,在过滤器放行时会自动调用包装类的getParameterValues方法,我们可以在包装类的getParameterValues方法中进行统一的请求参数过滤清理。
第九步:创建XssRequestWrapper类
package com.xbmu.wrapper;
import org.owasp.validator.html.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class XssRequestWrapper extends HttpServletRequestWrapper {
/* * 策略文件 需要将要使用的策略文件放到项目资源文件路径下 */
private static String antiSamyPath = XssRequestWrapper.class.getClassLoader()
.getResource("antisamy-test.xml").getFile();
public static Policy policy = null;
static {
// 指定策略文件
try {
policy = Policy.getInstance(antiSamyPath);
} catch (PolicyException 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.xbmu.config;
import com.xbmu.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 filterRegistration = new FilterRegistrationBean(new XssFilter());
filterRegistration.addUrlPatterns("/*");
filterRegistration.setOrder(1);
return filterRegistration;
}
}
启动项目,页面输入非法数据,可以看到非法数据被清理掉了。
注意:当前我们在进行请求参数过滤时只是在包装类的getParameterValues方法中进行了处理,真实项目中可能用户提交的数据在请求头中,也可能用户提交的是json数据,所以如果考虑所有情况,我们可以在包装类中的多个方法中都进行清理处理即可,如下:
package com.xbmu.wrapper;
import org.owasp.validator.html.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Map;
public class XssRequestWrapper extends HttpServletRequestWrapper {
/** * 策略文件 需要将要使用的策略文件放到项目资源文件路径下 * */
private static String antiSamyPath = XssRequestWrapper.class.getClassLoader()
.getResource( "antisamy-test.xml").getFile();
public static Policy policy = null;
static {
// 指定策略文件
try {
policy = Policy.getInstance(antiSamyPath);
} catch (PolicyException 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++){
// 过滤清理
newArray[j] = xssClean(values[j]);
}
return newArray;
}
@Override
public String getParameter(String paramString) {
String str = super.getParameter(paramString);
if (str == null) {
return null;
}
return xssClean(str);
}
@Override
public String getHeader(String paramString) {
String str = super.getHeader(paramString);
if (str == null) {
return null;
}
return xssClean(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++) {
values[i] = xssClean(values[i]);
}
}
return requestMap;
}
}

1.4、pd-tools-xss使用
pd-tools-xss的实现和我们上面的入门案例是一致的,底层也是基于AntiSamy对输入参数进行检验和清理,确保输入符合应用规范。为了方便使用,pd-tools-xss已经定义为了starter,其他应用只需要导入其maven坐标,不需要额外进行任何配置就可以使用。
具体使用过程:
第一步:创建maven工程并配置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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.xbmu</groupId>
<artifactId>myXssApp</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.itheima</groupId>
<artifactId>pd-tools-xss</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
第二步:创建XSSController
package com.xbmu.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/xss")
public class XSSController {
@GetMapping("/get")
public String get(String text){
return "处理之后的文本内容为:" + text;
}
}
第三步:创建启动类
package com.xbmu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class XssApplication {
public static void main(String[] args) {
SpringApplication.run(XssApplication.class,args);
}
}
启动项目,访问如下地址:

可以看到,如果输入的是普通文本则不做任何处理。如果输入的是特殊标签则被清理掉了。
边栏推荐
- Vivo official website app full model UI adaptation scheme
- Stm3 (cubeide) lighting experiment
- Beisen Holdings' IPO: a total loss of 4.115 billion yuan in three years, and a total of 2.84 billion yuan in the previous nine rounds of financing
- [depth] the new LAAS agreement elephant: the key to revitalizing the development of the defi track
- Canvas 填充渐变
- cv图像翻转,EmguCV图像旋转「建议收藏」
- An interview question about recover in golang
- JMeter distributed pressure measurement
- Differences between seaslog and monolog log systems, installation steps of seaslog [easy to understand]
- cts测试步骤(卡西欧cts200测试)
猜你喜欢

DDD的Go实战

浅谈web性能优化(一)

两数,三数之和

Canvas fill gradient

DDD go practice

Too many passwords, don't know how to record? Why don't you write a password box applet yourself

How to choose sentinel vs. hystrix current limiting?

Cesium polygon gradient texture (canvas)

Record the transfer of domain names from Alibaba cloud service providers to Huawei cloud

Airtest解决“自动装包”过程中需要输入密码的问题(同适用于随机弹框处理)
随机推荐
DDD go practice
mysql8.0 mha实现高可用《mha》
Kali modify the update source (it is not safe to update with this source)
有哪些优化mysql索引的方式请举例(sqlserver索引优化)
ZigBee IOT development platform (Industrial IOT)
黑盒(功能)测试基本方法
resize函数的作用「建议收藏」
day04_ array
seven point two three
图片怎么存储到数据库里「建议收藏」
Sqlx library usage
An interview question about interface and implementation in golang
An interview question combining defer and function in golang
腾讯云数据库的可信可控之路
GDB locates the main address of the program after strip
Decompile app
Temperature and humidity environment monitoring system based on stm32
接口测试工具 restlet client
Detailed explanation of JVM memory model and structure (five model diagrams)
As a test, how to understand thread synchronization and asynchrony