目录javascript
XSS,即(Cross Site Scripting)中文名称为“跨站脚本攻击”。
XSS的重点不在于跨站攻击而在于脚本攻击。攻击者能够利用 web应用的漏洞或缺陷之处,向页面注入恶意的程序或代码,以达到攻击的目的。
通俗的来讲就是咱们的页面在加载而且渲染绘制的过程当中,若是加载并执行了意料以外的程序或代码(脚本、样式),就能够认为是受到了 XSS攻击。php
document.cookie
盗取 cookie中的信息window.location.href
定位到其余页面)XSS 根据攻击是否持久,能够分为 “反射型XSS”与“存储型XSS”两种。
“反射型XSS”攻击者经过包装特定的链接,并将连接发送给实际的用户来进行攻击。
“反射型XSS”攻击通常是利用前端代码的漏洞或缺陷,好比使用 Eval来解析执行动态传入的数据,或者是一些被后端接受处理后再返回前端展现的 URL参数等,其操做手法很相似于钓鱼攻击。
“存储型XSS”攻击是经过表单提交,抓包工具,直接调用接口等形式向后端数据库注入数据。一旦被注入成功,并在输出的页面上没有作任何防范措施,那么全部访问这个页面的用户都会被攻击。
总的来讲,“反射型XSS”是一种局部非持久的针对性攻击,而“存储型XSS”就要严重的多,它是一个全面大范围可持久型的攻击。css
正常页面连接:html
http://xss-example.com/index.html?data={}
攻击者包装后的连接(data多是须要Eval解析的Json数据)前端
http://xss-example.com/index.html?data=alert(documet.cookie)
前端会被攻击的代码java
var data = eval('('+ getUrlParams('data') +')');
PS:固然在实际状况下,攻击者是不会把攻击代码这么明显的暴漏出来,通常都会通过编码。web
http://xss-example.com/index.html?data=\u0061\u006c\u0065\u0072\u0074(1)
若是你认为在解析 URL参数时不使用 Eval
便能保证安全,那就大错特错了,由于攻击者每每会主动的帮你执行 eval
。ajax
http://xss-example.com/index.html?url=http://exmaple.com
而后前端代码去解析并埋入一个 <a>
标记中。数据库
var _href = getUrlParams('url'); $('a').attr('href', _href);
可是,如今若是攻击者利用了您这个功能包装了这样的一条连接呢?express
http://xss-example.com/index.html?url=javascript:eval(alert(document.cookie));
编码以后:
http://xss-example.com/index.html?url=javascript:\u0065\u0076\u0061\u006c(\u0061\u006c\u0065\u0072\u0074(document.cookie));
如今有这样一个连接,URL参数会被后端的程序解析并返回给前端页面。
http://xss-example.com/index.html?name="xiaoming";
后端代码示例:
app.get('index.html', function (req, res) { res.send(req.query.name); })
若是如今用户访问的是这样的链接,有会怎么样呢?
http://xss-example.com/index.html?name=<script>alert(document.cookie)</script>
此时一个脚本标记就会被后端代码从新下发给前端,而后前端将其加入页面中,便会触发攻击行为。
固然,实际中并无这么可怕,由于 web程序自己就已经很好的进行了阻拦过滤,可是通过个人实际测试发现 Firefox与老版本的IE依然有这些问题,只有 Chrome 与新版本的IE进行了阻止。
若是你想再Chrome与新版本的IE浏览器中看到实际可产生的效果,能够经过设置 HTTP 的 Header头来关闭浏览器自动阻拦与过滤XSS功能。
app.get('index.html', function (req, res) { res.set('X-XSS-Protection', 0); //此处是关键 res.send(req.query.name); });
注入型攻击常见的地方就是留言评论或者是含有表单提交的地方。
例以下面咱们就以要给留言评论为例子来讲明注入型攻击:
首先,攻击者向一个textarea输入如下内容:
<script>alert(document.cookie)</script>
而后,前端调用 ajax
向后端传值
$('.send').click(function(){ $.post('message.htm',{'msg':$('textarea').val()},function(){}); });
接着,后端接收值写入数据库,同时又返回给前端展现。
app.post('message.htm',function(req,res,next){ //写入数据库 //... //响应前端 res.json({ test: req.body.msg }) });
最终当前端原样展现以前输入的攻击代码时,页面便发生了存储型攻击。
不管是反射型攻击仍是存储型,攻击者总须要找到两个要点,即“输入点”与"输出点",也只有这二者都知足,XSS攻击才会生效。“输入点”用于向 web页面注入所需的攻击代码,而“输出点”就是攻击代码被执行的地方。
大体上,攻击者进行XSS攻击要通过如下几个步骤:
首先是分析程序寻找漏洞,而后构建攻击代码,好比上面做为留言内容的 script
标签,实际上能够执行前端JS代码,远程加载JS脚本CSS样式文件的 HTML标签也很是多,好比:
#当图片不存在时,必然触发 onerror事件 <img src="null" onerror='alert(document.cookie)' /> #加载远程CSS文件,破坏当前页面的样式 <link href="test.css"> #点击的时候 <a onclick="alert(document.cookie)" onmouseover onmouseout></a> #鼠标移动的时候 <div onmouseover=‘do something here’> #破坏页面样式 <style>*{font-size:100px}</style> #利用IE7-的 css expression表达式的行为。 <div style="width:expression(alert('XSS'))">
当代码注入成功后,攻击者每每就须要去寻找所注入代码的输出点,例如百度网盘以前就有一个修改昵称的 XSS漏洞,虽然前端设置了字符长度为10个字符,可是攻击者经过使用抓包工具构建了一个 的执行脚本,并成功的注入到了数据库,后面测试发现,最终攻击的输出位置处于用户分享资源给其它好友时,展开好友列表的时刻。
实际上简单的经过正则判断 script、link、style、img 等HTML标记并不可取,由于,首先输入点的状况变化多样,很难把全部的 html标记的特性都考虑进来,其次对html标记的限制,也会让产品的可用性大大下降(好比有些特殊的关键字会被程序阻止,使得用户使用很是不便),最后这种判断自己也不安全,好比攻击者会在关键字中插入空格、制表符以及其它HTML实体编码来躲避侦测。
既然咱们前面说到攻击必须有两个要点:“输入点”,“输出点”,因此防护的时候,咱们只要作好这两个点的控制,就基本上能够万无一失!
document.cookie
读取 cookie,此 HTTP头由服务端设置。JSON.parse()
方法。就目前而言,应对XSS攻击的主要手段仍是编码与过滤两种,编码用于将特殊的符号 "<、>、&、'、""进行转义,而过滤则是阻止特定的标记、属性、事件。
若是你不肯意为了严格的安全而限制产品自己的灵活,那么我更建议采用“编码”的方案。
首先看下京东的搜索功能:
接着,再看下知乎提交评论时接口的数据:
最后,咱们再看下知乎时如何展现提交后的评论:
实际上实现上述的编码功能很是简单,咱们能够对照 HTML实体编码表 来进行正则匹配替换。
function encode(str) { if (!str || str.length === 0) return ''; str = str.replace(/>/gm, '>'); str = str.replace(/</gm, '<'); str = str.replace(/"/gm, '"'); str = str.replace(/'/gm, '''); return str; }
固然在实际应用中很难避免本身写的匹配规则就能万无一失,而且XSS攻击又一直是在变化的过程当中,所以我的更推荐使用第三方专门防护XSS攻击的库。
前面都是针对输入点的防护说明,在输出的状况下,前端开发人员应当要对本身采用的输出方法与输出方式要有必定的了解:
原生JS中
方法 | 说明 |
---|---|
innerHTML | 安全,可是IE8下危险(IE8支持可见的含有defers属性的script标记,例如:_) |
appendChild, insertBefored等 | 危险 |
innerText | 安全 |
Jquery中
方法 | 说明 |
---|---|
html() | 危险 |
before,after,append等 | 危险 |
text() | 安全 |
EJS模版
输出格式 | 说明 |
---|---|
<%= > | 危险,非转义的HTML输出 |
<%- > | 安全,转义的HTML输出 |
首先咱们了解了 XSS的定义,XSS即跨站点脚本攻击,只要浏览器加载,解析,执行了意料以外的JS,CSS等均可以被认为是受到了 XSS攻击,而 XSS攻击的分类主要有“反射型”与“存储型”两种。
“反射型”攻击者经过包装改造URL参数,而后利用前端代码的缺陷或漏洞来攻击,它更偏向与前端层面,而且在实际攻击中攻击者会根据 HTML实体编码、URL编码、uniocde编码等进行编码而后欺骗用户点击访问。而“存储型”攻击者则会经过抓包工具或者是直接调用接口的方式想尽一切办法来向后端数据库注入数据。
XSS攻击有两个要点,一个是“输入点”,针对输入点咱们能够对关键的特殊的字符进行编码,而在“输出点”咱们要对本身采用的输出方式以及方法要有必定的安全风险认知。
https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet (查看更多XSS攻击案例)