XSS攻击的解决方法

在我上一篇《前端安全之XSS攻击》文中,并无把XSS攻击的解决办法说完整,而XSS的攻击又那么五花八门,有没有一招“独孤九剑”可以抗衡,毕竟那么多状况场景,开发人员没法一一照顾过来,而今天经过阅读《白帽子讲Web安全》这本书,对应对方式有了更好的总结,分为两类,一是服务端能够干的事,二是客户端能够干的事。html

前提前端

在说XSS解决方式时,有一个前提。就是同源策略——浏览器的同源策略(浏览器安全的基础,即便是攻击脚本也要遵照这法则),限制了来自不一样源的“document”或脚本,对当前“document”读取或设置某些属性。除了DOM、Cookie、XMLHttpRequest会受到同源策略的限制外,浏览器加载的一些第三方插件也有各自的同源策略。不过script、img、iframe、link等标签均可以跨域加载资源,而不受同源策略的限制。jquery

服务端能够干的事后端

1. HttpOnly跨域

其实就是如今HTTP协议(HTTPS也是能够的)才能读取cookies,JavaScript是读取不到cookies的。支持浏览器是IE6+、Firefox2+、Google、Safari4+。浏览器

JavaEE给Cookie添加HttpOnly的代码:安全

response.setHeader("Set-Cookie","cookiename=value; Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");

PS:对于HTTPS,仍是能够设置Secure字段,对Cookie进行安全加密。服务器

这是本质上不是预防XSS,而是在被攻破时候不容许JS读取Cookie。cookie

2.处理富文本app

有些数据由于使用场景问题,并不能直接在服务端进行转义存储。不过富文本数据语义是完整的HTML代码,在输出时也不会拼凑到某个标签的属性中,因此能够当特殊状况特殊处理。处理的过程是在服务端配置富文本标签和属性的白名单,不容许出现其余标签或属性(例如script、iframe、form等),即”XSS Filter“。而后在存储以前进行过滤(过滤原理没有去探明)。

Java有个开源项目Anti-Samy是很是好的XSS Filter:

Policy ploicy = Policy.getInstance(POLICY_FILE_LOCATION);
AntiSamy as = new AntiSamy();
CleanResults cr = as.scan(dirtyInput, policy);
MyUserDao.storeUserProfile(cr.getCleanHTML());

PS:固然也能够在前端显示前过滤,可是我以为,让前端人员少作东西好,而且服务端只须要转一次。

客户端能够干的事

1. 输入检查

输入检查的逻辑,必须放在服务器端代码中实现(由于用JavaScript作输入检查,很容易被攻击者绕过)。目前Web开发的广泛作法,是同时在客户端JavaScript中和服务器代码中实现相同的输入检查。客户端JavaScript的输入检查,能够阻挡大部分误操做的正经常使用户,从而节约服务资源。

PS:简单说,就是输入检查,服务端和客户端都要作。

另外攻击者可能输入XSS的地方,例如:

1.页面中全部的input框
2.window.location(href、hash等)
3.window.name
4.document.referrer
5.document.cookie
6.localstorage
7.XMLHttpRequest返回的数据

PS:固然不止这些

2. 输出检查

通常就是在变量输出到HTML页面时,使用编码或转义的方式来防护XSS攻击。XSS的本质就是“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了本来的语义,产生了新的语义。

触发XSS的地方

1.document.write
2.xxx.innerHTML=
3.xxx.outerHTML=
4.innerHTML.replace
5.document.attachEvent
6.window.attachEvent
7.document.location.replace
8.document.location.assign

PS:若是使用jquery,就是那些append、html、before、after等,其实就是拼接变量到HTML页面时产生。大部分的MVC框架在模板(view层)会自动处理XSS问题,例如AngularJS。

用什么编码转义

主要有HTMLEncode和JavaScriptEncode这两个,客户端和服务端都能作。可是让后端去作,我感受是不大靠谱的,由于数据的使用场景可能有几种,能够在标签、属性、或脚本里(甚至其余终端使用),单单以一种方式去encode是很极限的。

1.HTMLEncode,就是将字符转换成HTMLEntities,通常会转(&、<、>、"、'、/)这6个字符。

2.JavaScriptEncode,是使用”\“对特殊字符进行转义。

PS:我在《HtmlEncode和JavaScriptEncode(预防XSS)》一文总结了比较完整的HTMLEncode和JavaScriptEncode两个前端函数的写法,以及一点示例。

哪些地方须要编转义

1.在HTML标签、属性中输出——用HTMLEncode

2.在script标签中输出——用JavaScriptEncode

3.在事件中输出——用JavaScriptEncode

<a href="#" onclick="funcA('$var')">test</a>

4.在CSS中输出

用相似JavaScriptEncode的方式。将除了字母、数字外的全部字符都编码成十六进制形式”\uHH“。

5.在地址中输出

通常若是变量是整个URL,则先检查变量是否以“http”开头(不是则帮忙添加http),保证不会出现伪协议类的XSS攻击。而后再对变量进行URLEncode。

PS:URLEncode会将字符转换成”%HH“形式。

总结

前端开发人员要注意在正确的地方使用正确的编码方式,有时为了防护XSS,在一个地方咱们须要联合HTMLEncode、JavaScriptEncode进行编码,甚至是叠加,并非固定一种方式编码(又是具体状况具体分析)。

通常存储型XSS风险高于反射型XSS。反射型XSS通常要求攻击者诱使用户点击一个包含XSS代码的URL连接;而存储型只须要用户查看一个正常的URL连接,当用户打开页面时,XSS Payload就会被执行。这样漏洞极其隐蔽,且埋伏在用户的正常业务中,风险很高。(引自白帽子讲Web安全原文)

本文为原创文章,转载请保留原出处,方便溯源,若有错误地方,谢谢指正。

本文地址 :http://www.cnblogs.com/lovesong/p/5223989.html

相关文章
相关标签/搜索