21.浅谈前端WEB安全性(二)

(二)浅谈前端WEB安全性
5.XSS防御
6.XSS分类及挖掘方法

5.XSS防御

一.概述

攻击者可以利用XSS漏洞向用户发送攻击脚本,而用户的浏览器因为没有办法知道这段脚本是不可信的,所以依然会执行它。

a:输入检查,服务端和客户端都要做。

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

b:输出检查 在变量输出到html页面时,可以使用HtmlEncode来防御XSS攻击,JS中可以使用JavascriptEncode。

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
如果使用jquery,append、html、before、after等,其实就是拼接变量到HTML页面时产生。
大部分的MVC框架在模板(view层)会自动处理XSS问题,例如AngularJS。

用什么编码转义

1.HTMLEncode,就是将字符转换成HTMLEntities,一般会转[&、<、>、"、'、/]这6个字符。
2.JavaScriptEncode,是使用”\“对特殊字符进行转义。

哪些地方需要什么编码转义

1.在HTML标签、属性中输出——用HTMLEncode
2.在script标签中输出——用JavaScriptEncode
3.在事件中输出——用JavaScriptEncode
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安全原文)

二.8条规则将详细介绍如何在正确的地方使用正确的编码来消除XSS漏洞。

原则1:不要在页面中插入任何不可信数据,除非这些数已经据根据下面几个原则进行了编码

因为HTML里有太多的地方容易形成XSS漏洞,而且形成漏洞的原因又有差别,比如有些漏洞发生在HTML标签里,有些发生在HTML标签的属性里,还有的发生在页面的

===》

[编码规则]它需要对下面这6个特殊字符进行编码:

&     –>     &
<     –>     <
>     –>     >
”     –>     "
‘     –>     '
/     –>     /

特别说明的是: 需要对斜杠号( / )编码,因为在进行XSS攻击时,斜杠号对于关闭当前HTML标签非常有用

原则3:在将不可信数据插入到[HTM标签属性]里时,对这些数据进行[HTML属性编码]

HTML属性(例如width、name、value属性)的值部分插入不可信数据的时候,应该对数据进行HTML属性编码。但是插入HTML标签的事件处理属性(例如onmouseover),本条原则不适用,应该用下面介绍的原则4对其进行JavaScript编码。

===》
<"">

[编码规则]
除了阿拉伯数字和字母,对其他所有的字符进行编码,只要该字符的ASCII码小于256。编码后输出的格式为 &#xHH; (以&#x开头,HH则是指该字符对应的十六进制数字,分号作为结束符)

例如,如果属性没有使用引号,又没有对数据进行严格编码,那么一个空格符就可以闭合掉当前属性。请看下面这个攻击:

假设HTML代码是这样的:
…content…
攻击者可以构造这样的输入: x onmouseover=”javascript:alert(/xss/)” 最后,在用户的浏览器里的最终HTML代码会变成这个样子:
…content…

只要用户的鼠标移动到这个DIV上,就会触发攻击者写好的攻击脚本。在这个例子里,脚本仅仅弹出一个警告框,除了恶作剧一下也没有太多的危害,但是在真实的攻击中,攻击者会使用更加具有破坏力的脚本,例如下面这个窃取用户cookie的XSS攻击:

x />  

原则4:在将不可信数据插入到SCRIPT里时,对这些数据进行SCRIPT编码

这条原则主要针对动态生成的JavaScript代码,这包括脚本部分以及HTML标签的事件处理属性

[编码规则]

在对不可信数据做编码的时候,千万不能图方便使用反斜杠( \ )对特殊字符进行简单转义 ,这样做是不可靠的。因为浏览器在对页面做解析的时候,会先进行HTML解析,然后才是JavaScript解析

假设代码片段如下:


攻击者输入的内容为:

\";alert('xss');//

如果只是对双引号进行简单转义,将其替换成 "的话,攻击者输入的内容在最终的页面上会变成:


浏览器在解析的时候,会认为反斜杠后面的那个双引号和第一个双引号相匹配,继而认为后续的alert(‘xss’)是正常的JavaScript脚本,因此允许执行。

原则5:在将不可信数据插入到Style属性里时,对这些数据进行CSS编码

Style标签或者Style属性里插入不可信数据的时候,需要对这些数据进行CSS编码。应该只允许把不可信数据放入到CSS属性的值部分,并进行适当的编码。

原则6:在将不可信数据插入到HTML URL里时,对这些数据进行URL编码

在地址中输出:一般是在URL的path(路径)或者search(参数)中输出。
攻击方法:
a)
test 
===》  
test
b)
   
===》构造伪协议实施攻击。


[编码规则]
在对URL进行编码的时特别注意的:不要对整个URL进行编码,因为不可信数据可能会被插入到href, src或者其他以URL为基础的属性里,这时需要对数据的起始部分的协议字段进行验证,否则攻击者可以改变URL的协议,例如从HTTP协议改为DATA伪协议,或者javascript伪协议。先检查变量是否以”http“开头(如果不是则自动添加),以保证不会出现伪协议类的XSS攻击。在此之后,再对变量进行URLEncode。

原则7:使用富文本时,使用XSS规则引擎进行编码过滤

富文本允许用户提交一些自定义的HTML代码,比如BBS发帖,写博客文章等,用户提交的富文本信息里往往包含了HTML标签,甚至是JavaScript脚本,如果不对其进行适当的编码过滤的话,则会形成XSS漏洞。

[编码规则]
在标签、属性、事件的选择上,应该使用白名单,避免使用黑名单。比如,一些危险的标签: