同源策略
在介绍 XSS 之前首先来了解一下同源策略,因为它是浏览器最核心也最基本的安全功能。
同源 (协议、host(域名或 IP 地址,如果是 IP 地址则看作一个根域名)、端口号相同) 策略限制了来自不同源的 ”document” 或脚本,对当前 ”document” 读取或设置某些属性。
script、img、iframe、link 等标签都可以跨域加载资源,它实际上是由浏览器发起了一次 GET 请求。不同于 XMLHttpRequest 的是,浏览器限制了 JavaScript 的权限,使其不能读、写返回的内容。XMLHttpRequest 受到同源策略的约束,不能跨域访问资源。
什么是 XSS
XSS 攻击,通常指黑客通过 ”HTML 注入 ” 篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。一开始,这种攻击的演示案例是跨域的,所以叫做 ” 跨站脚本 ”,现在是否跨域已经不再重要,但是名字一直沿用下来。
XSS 示例
假如用户输入的参数直接输出到页面上:
<?php
$input = $_GET["param"];
echo "<div>".$input."</div>";
?>
用户提交了一段 HTML 代码
http://www.a.com/test.php?param=<script>alert(/xss/)</script>
alert(/xss/)就会在页面中执行。
这就是 XSS 的一种:反射型 XSS。
XSS 分类
- 反射型 XSS
反射型 XSS 只是简单地把用户输入的数据”反射“给浏览器。也就是说黑客往往需要诱使用户”点击“一个恶意链接,才能攻击成功。反射型 XSS 也叫”非持久型 XSS”。
- 存储型 XSS
存储型 XSS 会把用户输入的数据“存储”在服务器端。这种 XSS 具有很强的稳定性。
比较常见的,黑客写下一篇包含恶意 JavaScript 代码的博客文章,文章发表后,所有访问该博客文章的用户,都会在他们的浏览器中执行这段恶意的 JavaScript 代码。黑客把恶意脚本保存在了服务端,这种 XSS 攻击就叫做“存储型 XSS”。存储型 XSS 也叫做“持久型 XSS”。
- DOM Based XSS
通过修改页面的 DOM 节点形成的 XSS,称之为 DOM Based XSS,从效果上来说也是反射型 XSS,单独划分出来是因为它的形成原因比较特殊,发现它的安全专家提出了这种类型的 XSS。出于历史原因把它单独作为一个分类了。
DOM Based XSS 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<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()" />
</body>
</html>
输入框构造如下数据:
' onclick=alert(/xss/) //
它先用一个单引号闭合掉 href 的第一个单引号,然后插入一个 onclick 事件,最后再用注释符“//”注释掉第二个引号。
输入后,页面代码变成了:
<a href=""onclick="alert(/xss/)" '>testLink</a>
点击新生成的这个链接,脚本将被执行。
其实还可以选择闭合掉 <a>
标签,并插入一个新的 HTML 标签:
'><img src=# onerror=alert(/xss2/) /><'
页面代码变成
<a href="">
<img src="#" onerror="alert(/xss2/)"><''>
testLink
</a>
脚本直接被执行,弹出 /xss2/。