Web安全头号大敌XSS漏洞解决最佳实践
Posted IT技术小咖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web安全头号大敌XSS漏洞解决最佳实践相关的知识,希望对你有一定的参考价值。
XSSXSS 代码攻击及危害分析 ——> <script
快速创建 springboot 应用: <groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>1.5.7</version>
* @program: xss-demo* @author: Mr.Zhang
* @create: 2021-02-21 15:45
**/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getServletPath();
//注解配置的是urlPatterns="/*"(过滤所有请求),所以这里对不需要过滤的静态资源url,作忽略处理(大家可以依照具体需求配置)
String[] exclusionsUrls = ".js", ".gif", ".jpg", ".png", ".css", ".ico";
for (String str : exclusionsUrls)
if (path.contains(str))
chain.doFilter(request, response);
return;
chain.doFilter(new XssRequestWrapper(httpServletRequest), response);
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:46
**/
public XssRequestWrapper(HttpServletRequest request)
super(request);
/**
* 获取策略文件,直接使用jar中自带的ebay策略文件
*/
private static InputStream inputStream = XssRequestWrapper.class.getClassLoader()
.getResourceAsStream("antisamy-ebay.xml");
private static Policy policy = null;
static
try
// 使用静态代码块处理策略对象的创建
policy = Policy.getInstance(inputStream);
catch (PolicyException e)
e.printStackTrace();
/**
* 使用AntiSamy进行过滤数据
* @param html
* @return
*/
private String xssClean(String html)
String cleanHTML = "";
try
AntiSamy antiSamy = new AntiSamy();
CleanResults scan = antiSamy.scan(html, policy);
cleanHTML = scan.getCleanHTML();
catch (ScanException e)
e.printStackTrace();
catch (PolicyException e)
e.printStackTrace();
return cleanHTML;
/**
* 重写处理请求参数的方法
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name)
String[] values = super.getParameterValues(name);
// 判断参数有值,如果没有值,直接返回
if (values == null)
return null;
// 遍历参数数组,使用AntiSamy进行过滤
int len = values.length;
String[] newValues = new String[len];
for (int i = 0; i < len; i++)
// 过滤前的数据
log.info("使用AntiSamy进行过滤清理,过滤清理之前的数据:", values[i]);
// 进行过滤
newValues[i] = xssClean(values[i]);
// 过滤后的数据
log.info("使用AntiSamy进行过滤清理,过滤清理之后的数据:", newValues[i]);
//返回过滤后的结果
return newValues;
/**
* 重写处理json数据的方法
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException
// 读取流
BufferedReader reader = new BufferedReader(
new InputStreamReader(super.getInputStream(), "UTF-8"));
// 获取json格式的数据
StringBuilder sb = new StringBuilder();
String inputStr;
while ((inputStr = reader.readLine()) != null)
sb.append(inputStr);
// 把json转为map
Map map = JSON.parseObject(sb.toString(), Map.class);
// 过滤前
log.info("json过滤前:", sb.toString());
// 对map中的value值进行AntiSamy的过滤
map.keySet().forEach(k ->
map.put(k, xssClean(map.get(k).toString()));
);
// 过滤后
String json = JSON.toJSONString(map);
log.info("json过滤后:", json);
// 把json数据转为流的格式进行返回
ByteArrayInputStream bais = new ByteArrayInputStream(json.getBytes());
return new ServletInputStream()
@Override
public boolean isFinished()
return false;
@Override
public boolean isReady()
return false;
@Override
public void setReadListener(ReadListener listener)
@Override
public int read() throws IOException
return bais.read();
;
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:58
**/
/**
* 配置xss过滤器
* @return
*/
@Bean
public FilterRegistrationBean create()
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:42
private int id;
private String name;
private int age;
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:43
**/
/**
* 表单
* @param user
* @return
*/
@PostMapping("save")
public String save(User user)
log.info("name=, age=", user.getName(), user.getAge());
return JSON.toJSONString(user);
/**
* json数据格式请求体
* @param user
* @return
*/
@PostMapping("json")
public String saveJson(@RequestBody User user)
log.info("user=", user.toString());
return JSON.toJSONString(user);
content="form-action \'self\';">
CSP 常见可选策略设置如下:
策略 含义 default-src http: https: ; 只能通过外联的方式引用 js 和 css default-src \'self\' http://smart4j.cn/; 只能在指定的域下加载文件(包含 img) form-action \'self\'\'; form 表单的只能在指定域提交 script-src \'self\'; 只限制 js 文件在同域加载文件 report-uri /report; 向指定uri发送违规报告(不支持 meta 方式)
加油
# 精彩推荐 #
分布式系统「全链路日志追踪」实战之 RestTemplate & Feign
小白都能看得懂的服务调用链路追踪设计与实现
[三步法] 可视化分析定位线上 JVM 问题
从 Java 代码如何运行聊到 JVM 和对象的创建-分配-定位-布局-垃圾回收
深入了解 Spring 中的事务(从核心注解和类入手)
"在看"吗,赶快分享和收藏吧
XSS漏洞简介
0x01.什么是XSS
全称:Cross Site Script
中文名称:跨站脚本
按英文缩写应该是CSS,为了与层叠样式表CSS做区分,安全行业就取名为XSS。
XSS是客户端安全的头号大敌,常见的危害有:盗取cookie,钓鱼,制造蠕虫等。
XSS其实是客户端代码的注入,通常注入代码是JAVAScript
区别于命令注入,SQL注入等服务端代码注入
概念:黑客通过 ‘HTML注入’ 篡改网页,插入恶意脚本,当用户在浏览网页时,实现控制用户浏览器行为的一种攻击方式。
0x02.xss的分类
存储型
反射性
DOM型
存储型:一般在查看留言,看评论的时候触发。
下面我们分析下存储型XSS的攻击过程:
1.用户打开浏览器,访问了嵌入xss脚本的页面
2.浏览器向web应用程序请求页面。
3.页面中的留言存储在数据库中,需要web应用程序查询数据库
4.数据库会将携带xss脚本的留言返回给web应用程序
5.web应用程序返回给浏览器
6.显示在浏览器上,触发XSS。
这里xss脚本是存储在数据库中,那么是什么时候保存到数据库中的呢?。肯定是黑客构造XSS脚本并写入到数据库中。
1.黑客精心构造XSS脚本提交给web应用程序。
2.web应用程序将恶意留言保存到数据库中。
3.其他用户或者管理员在查看留言时就跟前面展示的一样触发XSS。
存储型xss关键点:xss脚本内容是存储在数据库中
反射型:一般需要我们访问携带XSS脚本的链接触发,xss在URL的参数中,比如通过邮件,聊天工具发送链接,只要我们打开这个链接就触发了XSS,反射型xss可以在链接中明显的看到xss脚本。
下面我们分析反射性XSS的攻击过程:
用户访问问含有xss脚本的链接
浏览器向后端web程序发送请求
后端web程序将URL中的XSS数据脚本写入响应页面
返回给浏览器
浏览器渲染响应页面,触发XSS
DOM型:与反射型需要访问携带XSS脚本的链接触发,xss脚本在URL的哈希中。
下面我们分析DOM型XSS的攻击过程:
1.用户访问含有XSS脚本的链接
2.浏览器通过JAvascript从URL中提取XSS的脚本内容
3.写入DOM中触发XSS
0x03.三种XSS比较
以上是关于Web安全头号大敌XSS漏洞解决最佳实践的主要内容,如果未能解决你的问题,请参考以下文章
<script
<artifactId>antisamy</artifactId>
<version>1.5.7</version>
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:45
**/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getServletPath();
//注解配置的是urlPatterns="/*"(过滤所有请求),所以这里对不需要过滤的静态资源url,作忽略处理(大家可以依照具体需求配置)
String[] exclusionsUrls = ".js", ".gif", ".jpg", ".png", ".css", ".ico";
for (String str : exclusionsUrls)
if (path.contains(str))
chain.doFilter(request, response);
return;
chain.doFilter(new XssRequestWrapper(httpServletRequest), response);
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:46
**/
public XssRequestWrapper(HttpServletRequest request)
super(request);
/**
* 获取策略文件,直接使用jar中自带的ebay策略文件
*/
private static InputStream inputStream = XssRequestWrapper.class.getClassLoader()
.getResourceAsStream("antisamy-ebay.xml");
private static Policy policy = null;
static
try
// 使用静态代码块处理策略对象的创建
policy = Policy.getInstance(inputStream);
catch (PolicyException e)
e.printStackTrace();
/**
* 使用AntiSamy进行过滤数据
* @param html
* @return
*/
private String xssClean(String html)
String cleanHTML = "";
try
AntiSamy antiSamy = new AntiSamy();
CleanResults scan = antiSamy.scan(html, policy);
cleanHTML = scan.getCleanHTML();
catch (ScanException e)
e.printStackTrace();
catch (PolicyException e)
e.printStackTrace();
return cleanHTML;
/**
* 重写处理请求参数的方法
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name)
String[] values = super.getParameterValues(name);
// 判断参数有值,如果没有值,直接返回
if (values == null)
return null;
// 遍历参数数组,使用AntiSamy进行过滤
int len = values.length;
String[] newValues = new String[len];
for (int i = 0; i < len; i++)
// 过滤前的数据
log.info("使用AntiSamy进行过滤清理,过滤清理之前的数据:", values[i]);
// 进行过滤
newValues[i] = xssClean(values[i]);
// 过滤后的数据
log.info("使用AntiSamy进行过滤清理,过滤清理之后的数据:", newValues[i]);
//返回过滤后的结果
return newValues;
/**
* 重写处理json数据的方法
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException
// 读取流
BufferedReader reader = new BufferedReader(
new InputStreamReader(super.getInputStream(), "UTF-8"));
// 获取json格式的数据
StringBuilder sb = new StringBuilder();
String inputStr;
while ((inputStr = reader.readLine()) != null)
sb.append(inputStr);
// 把json转为map
Map map = JSON.parseObject(sb.toString(), Map.class);
// 过滤前
log.info("json过滤前:", sb.toString());
// 对map中的value值进行AntiSamy的过滤
map.keySet().forEach(k ->
map.put(k, xssClean(map.get(k).toString()));
);
// 过滤后
String json = JSON.toJSONString(map);
log.info("json过滤后:", json);
// 把json数据转为流的格式进行返回
ByteArrayInputStream bais = new ByteArrayInputStream(json.getBytes());
return new ServletInputStream()
@Override
public boolean isFinished()
return false;
@Override
public boolean isReady()
return false;
@Override
public void setReadListener(ReadListener listener)
@Override
public int read() throws IOException
return bais.read();
;
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:58
**/
/**
* 配置xss过滤器
* @return
*/
@Bean
public FilterRegistrationBean create()
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:42
private int id;
private String name;
private int age;
* @program: xss-demo
* @author: Mr.Zhang
* @create: 2021-02-21 15:43
**/
/**
* 表单
* @param user
* @return
*/
@PostMapping("save")
public String save(User user)
log.info("name=, age=", user.getName(), user.getAge());
return JSON.toJSONString(user);
/**
* json数据格式请求体
* @param user
* @return
*/
@PostMapping("json")
public String saveJson(@RequestBody User user)
log.info("user=", user.toString());
return JSON.toJSONString(user);
content="form-action \'self\';">
加油
# 精彩推荐 #
分布式系统「全链路日志追踪」实战之 RestTemplate & Feign
小白都能看得懂的服务调用链路追踪设计与实现
[三步法] 可视化分析定位线上 JVM 问题
从 Java 代码如何运行聊到 JVM 和对象的创建-分配-定位-布局-垃圾回收
深入了解 Spring 中的事务(从核心注解和类入手)
"在看"吗,赶快分享和收藏吧
XSS漏洞简介
0x01.什么是XSS
全称:Cross Site Script
中文名称:跨站脚本
按英文缩写应该是CSS,为了与层叠样式表CSS做区分,安全行业就取名为XSS。
XSS是客户端安全的头号大敌,常见的危害有:盗取cookie,钓鱼,制造蠕虫等。
XSS其实是客户端代码的注入,通常注入代码是JAVAScript
区别于命令注入,SQL注入等服务端代码注入
概念:黑客通过 ‘HTML注入’ 篡改网页,插入恶意脚本,当用户在浏览网页时,实现控制用户浏览器行为的一种攻击方式。
0x02.xss的分类
存储型
反射性
DOM型
存储型:一般在查看留言,看评论的时候触发。
下面我们分析下存储型XSS的攻击过程:
1.用户打开浏览器,访问了嵌入xss脚本的页面
2.浏览器向web应用程序请求页面。
3.页面中的留言存储在数据库中,需要web应用程序查询数据库
4.数据库会将携带xss脚本的留言返回给web应用程序
5.web应用程序返回给浏览器
6.显示在浏览器上,触发XSS。
这里xss脚本是存储在数据库中,那么是什么时候保存到数据库中的呢?。肯定是黑客构造XSS脚本并写入到数据库中。
1.黑客精心构造XSS脚本提交给web应用程序。
2.web应用程序将恶意留言保存到数据库中。
3.其他用户或者管理员在查看留言时就跟前面展示的一样触发XSS。
存储型xss关键点:xss脚本内容是存储在数据库中
反射型:一般需要我们访问携带XSS脚本的链接触发,xss在URL的参数中,比如通过邮件,聊天工具发送链接,只要我们打开这个链接就触发了XSS,反射型xss可以在链接中明显的看到xss脚本。
下面我们分析反射性XSS的攻击过程:
用户访问问含有xss脚本的链接
浏览器向后端web程序发送请求
后端web程序将URL中的XSS数据脚本写入响应页面
返回给浏览器
浏览器渲染响应页面,触发XSS
DOM型:与反射型需要访问携带XSS脚本的链接触发,xss脚本在URL的哈希中。
下面我们分析DOM型XSS的攻击过程:
1.用户访问含有XSS脚本的链接
2.浏览器通过JAvascript从URL中提取XSS的脚本内容
3.写入DOM中触发XSS
0x03.三种XSS比较
以上是关于Web安全头号大敌XSS漏洞解决最佳实践的主要内容,如果未能解决你的问题,请参考以下文章