跨站脚本攻击是客户端脚本安全中的头号大敌。OWASP TOP 10威胁多次把XSS列在榜首。
3.1 XSS简介
XSS攻击通常是指黑客通过“HTML”注入篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。
分类
- 反射型XSS: 简单的将用户输入的数据”反射“给浏览器。黑客往往需要诱使用户点击一个恶意链接,才能攻击成功,存在时间短
- 存储型XSS: 把用户的输入数据”存储“在服务器端。黑客将恶意的脚本保存到服务器端,访问该服务器的用户就会在他们的浏览器中执行这个恶意脚本,存在时间长
- DOM型XSS: 通过修改页面的DOM节点形成的XSS
<script>
function test(){
var str = document.getElementById("text").value;
document.getElementById("t").innerHTML = "<a href='"+str+"' >testLink</a>";
}
</script>
<div id="t" ></div>
<input type="text" id="text" value="" />
<input type="button" id="s" value="write" onclick="test()" />
点击”write“按钮之后,当前页面出现超链接:
构造如下数据:
onclick=alert(/xss/) //
输入后页面代码变为:
<a href='' onclick=alert(/xss/)//' >testLink</a>
这里首先用一个单引号闭合掉href的第一个单引号,然后插入一个onclick事件,最后注释符”//“注释叼第二个单引号
3.2 XSS进阶
XSS攻击成功后,攻击者可以对用户当前浏览页面植入恶意脚本,进而控制浏览器
常见攻击场景
- 构造GET和POST请求
- XSS钓鱼: 例如窃取用户密码,攻击者将XSS与”钓鱼“相结合,利用JavaScript在当前页面上伪造一个登录框,窃取用户名和密码
- 识别用户浏览器: 最直接的就是通过XSS读取浏览器的UserAgent对象
- 识别用户安装软件
- CSS History Hack
- 获取真实IP: Attack API
XSS构造技巧
-
利用字符编码:”百度搜藏“转义双引号,导致变量无法”escape“
var redirectUrl="\";alert(/XSS/);"; -
绕过长度限制: 假设有以下代码存在XSS漏洞
<input data=text value="$var" />服务器对变量”$var“做了严格的长度限制,攻击者可以构造如下XSS尝试取绕过长度限制:
$var: "><script>alert(/xss/)</script> -
使用base标签: base标签定义页面上所有使用”相对路径“标签的hosting地址
-
使用window.name: 实现跨域、跨页面传输数据
-
Flash XSS: 将Flash嵌入页面
-
XSS Worm
3.3 XSS防御
XSS防御十分复杂,这里主要侧重于网站设计安全
- HttpOnly:浏览器页面禁止JavaScript访问带有HttpOnly属性的Cookie,解决XSS后的Cookie劫持攻击
- 输入检查: 输入检查一般检查用户输入的数据是否包含特殊字符,若发现则要对这些字符进行过滤或者编码处理,检查逻辑必须在服务器端进行(客户端容易被绕过)
- 输出检查: 转义或者编码
- 安全的编码函数: 各种编程语言中各有不同,如PHP中有htmlentities()和htmlspecialchar(),HTML中编码方式为HtmlEncode,JavaScript中使用JavascriptEncode等
- 处理富文本: 主要思路还是输入检查,严格禁止”事件“,标签选择上使用白名单
3.4 比较
一般来说,存储型XSS风险高于反射型XSS,因为它一直保存在服务器上,有可能跨页面存在。从攻击过程来说,反射型XSS一般要求攻击者诱使用户点击一个包含XSS的URL链接;而存储型XSS,则只需要用户查看正常的URL链接。XSS漏洞复杂,针对不同场景使用不同的方法,并要深入理解XSS的攻击原理。
| 类型 | 存储型 | 反射型 | DOM型 |
|---|---|---|---|
| 数据存储 | 数据库 | URL | URL |
| 输出端 | Web后端 | Web后端 | JS前端 |
| 输出位置 | Http响应中 | Http响应中 | DOM节点 |