跨站脚本攻击(XSS)是客户端脚本安全的头号大敌。本文章深刻探讨 XSS 攻击原理,下一章(XSS 攻击进阶)将深刻讨论 XSS 进阶攻击方式。javascript
本系列将持续更新。html
XSS(Cross Site Script),全称跨站脚本攻击,为了与 CSS(Cascading Style Sheet) 有所区别,因此在安全领域称为 XSS。java
XSS 攻击,一般指黑客经过 HTML 注入 篡改网页,插入恶意脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击行为。在这种行为最初出现之时,全部的演示案例全是跨域行为,因此叫作 "跨站脚本" 。时至今日,随着Web 端功能的复杂化,应用化,是否跨站已经不重要了,但 XSS 这个名字却一直保留下来。git
随着 Web 发展迅速发展,JavaScript 通吃先后端,甚至还能够开发APP,因此在产生的应用场景愈来愈多,愈来愈复杂的状况下, XSS 越来越难统一针对,如今业内达成的共识就是,针对不一样的场景而产生的不一样 XSS ,须要区分对待。可即使如此,复杂应用仍然是 XSS 滋生的温床,尤为是不少企业实行迅捷开发,一周一版本,两周一大版本的状况下,忽略了安全这一重要属性,一旦遭到攻击,后果将不堪设想。github
那什么是 XSS 呢?咱们看下面一个例子。npm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>XSS</title>
</head>
<body>
<div id="t"></div>
<input id="s" type="button" value="获取数据" onclick="test()">
</body>
<script> function test() { // 假设从后台取出的数据以下 const arr = ['1', '2', '3', '<img src="11" onerror="alert(\'我被攻击了\')" />'] const t = document.querySelector('#t') arr.forEach(item => { const p = document.createElement('p') p.innerHTML = item t.append(p) }) } </script>
</html>
复制代码
这个时候咱们在页面上点击 获取数据
按钮时,页面上会出现以下信息:后端
你会发现,本应该做为数据展现在界面上的内容竟然执行了,这显然是开发者不但愿看到的。跨域
XSS 根据效果的不一样能够分为以下几类:浏览器
简单来讲,反射型 XSS 只是将用户输入的数据展示到浏览器上(从哪里来到哪里去),即须要一个发起人(用户)来触发黑客布下的一个陷阱(例如一个连接,一个按钮等),才能攻击成功,通常容易出如今搜索页面、留言板块。这种反射型 XSS 也叫作 非持久型 XSS(No-persistent XSS) 。安全
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="t"></div>
<input id="s" type="button" value="获取数据" onclick="test()">
</body>
<script> function test() { const arr = ['1', '2', '3', '<img src="11" onerror="console.log(window.localStorage)" />'] const t = document.querySelector('#t') arr.forEach(item => { const p = document.createElement('p') p.innerHTML = item t.append(p) }) } </script>
</html>
复制代码
假设这是一个留言板块,加载到这一页时,页面会输出:
黑客能够轻易盗取存储在你本地浏览器的各类信息,进而模拟登录信息,黑入帐户,进行各类操做。
存储型 XSS 会把用户输入的数据 保存 在服务器端,这种 XSS 十分稳定,十分有效,效果持久。存储型 XSS 一般叫作 "持久型 XSS(Persistent XSS)",即存在时间比较长。
比较常见的场景就是,黑客写下一篇包含恶意代码的文章,文章发表后,全部访问该博客文章的用户都会执行这一段代码,进行恶意攻击。
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="t">
这是我写的一篇文章
</div>
</body>
<script> console.log(navigator.userAgent) </script>
</html>
复制代码
直接输出了浏览器信息,黑客能够获取到这些信息后,发送到本身的服务器,随意操做。
实际上,这种类型的 XSS 与是否存储在服务器端无关,从效果上来讲也是反射型 XSS,单独划分出来是由于此类 XSS 造成的缘由比较特殊。
简单来讲,经过修改页面 DOM 节点造成的 XSS,称之为 DOM Based XSS。
例子以下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>XSS</title>
</head>
<body>
<div id="t"></div>
<input type="text" id="text" value="">
<input type="button" id="s" value="search" onclick="test()">
</body>
<script> function test() { const str = document.querySelector('#text').value document.querySelector('#t').innerHTML = '<a href="' + str + '" >查找结果</a>' } </script>
</html>
复制代码
该页面的做用是,在输入框内输入一个内容,跳出查找结果能直接跳转,效果以下:
点击查找结果后,页面会自动跳到百度(毒)页面,可是细心的咱们会发现,这字符串拼接有可乘之机啊,输入" onclick=alert(/XSS/) //
:
果真,页面执行了咱们输入的东西,上面的内容是,第一个双引号闭合掉href
的第一个双引号,而后插入onclick
事件,最后注释符 //
注释掉第二个双引号,点击跳转连接,脚本就被执行了。
最后很差意思推广一下我基于 Taro
框架写的组件库:MP-ColorUI。
能够顺手 star 一下我就很开心啦,谢谢你们。