正确地防御XSS 笔记

正确地防御XSS

要想更好的设计XSS防御方案,需要认清XSS产生的本质原因。XSS的本质还是一种HTML注入,用户的数据被当成了HTML代码的一部分执行。从而混淆了原本的语义,产生了新的语义。

如果网站使用了MVC架构,那么XSS就发生在View层——在应用拼接变量到HTML页面时产生。所以在用户提交数据处进行输入检查的方案,其实并不是在真正发生攻击的地方做防御。

想要根治XSS问题,可以列出所有XSS可能发生的场景,再一一解决。

下面用$var表示用户数据,它将被填充入HTML代码中。可能存在与以下场景

XSS可能出现的场景。

在HTML标签中输出

所有在标签中输出的变量,如果未做任何处理,都能导致直接产生XSS

 所有在标签中输出的变量,如果未做任何处理,都能导致直接产生XSS

这种场景下,XSS的利用方式一般是构造一个<script>标签,或者是任何能够产生脚本执行的方式。比如

或者

 防御方法是对变量使用HtmlEncode。

在HTML属性中输出

与HTML标签中输出类似,可能的攻击方法:

防御方法也是采用HtmlEncode。

在OWASP ESAPI中推荐了一种更严格的HtmlEncode——除了字母、数字外,其他所有的特殊字符都被编码成HTMLEntities

这种严格的编码方式可以保证不会出现任何安全问题

在<script>标签中输出

在<script>标签中输出时,首先应该确保输出的变量在引号中:

攻击者需要先闭合引号才能实施XSS攻击 

 防御时使用javascriptEncode

在事件中输出

在事件中输出和在<script>标签中输出类似

 可能的攻击方法

 在防御时需要使用JavascriptEncode。

在CSS中输出

 一般来说,尽可能禁止用户可控制的变量在<style>标签、HTML标签的上腾娱乐属性以及CSS文件中输出,如果一定有这样的需求,则推荐使用OWASP ESAPI中的encodeForCSS()函数。

在地址中输出

在地址中输出也比较复杂。一般来说,在URL的path(路径)或者search(参数)中输出,使用URLEncode即可。URLEncode会将字符转换为%HH形式,比如空格就是“ %20 ”,“<”是“%3c”

 可能的攻击方法

 但是还有一种情况,就是整个URL能够被用户完全控制,这时的URL的Protocol和Host部分是不能够使用URLEncode的,否则会改变URL的语义。

一个URL的组成部分如下

在Protocal与Host中,如果使用严格的URLEncode函数,则会把“://”、“.”等都编码掉。

对于如下的输出方式,攻击者可能会构造伪协议实施攻击

 除了JavaScript作为伪协议可以执行代码外,还有“vbscript”、“dataURI”等伪协议可能导致脚本执行。“dataURI” 这个伪协议是Mozila所支持的,能够将一段代码写在URL里。如下例

这段代码的意思是以text/html的格式加载编码为base64的数据,而加载完成后实际上是:

点击 <a>标签的链接,将导致其执行脚本。由此可见,如果用户能够完全控制URL,则可以执行脚本的方式有很多,该怎么防范这种情况呢 

 一般来说,如果变量是整个URL,则应该检查变量是否以http开通,如果不是则自动添加,以保证不会出现协议类类型的XSS攻击。在此之后在对变量进行URLEncode,就可以保证不会有此类XSS发生了。

处理富文本

有些时候,网站需要允许用户提交一些自定义的HTML代码,称之为“富文本”。比如一个用户在论坛里发帖,帖子里的内容要有图片、视频、表格等,这些富文本的效果都需要通过HTML代码来实现。

那么该如何区分安全的富文本和有攻击性的XSS?

在处理富文本时,还是要回到输入检查的思路上来。“输入检查”的主要问题是,在检查时还不知道变量的输出语境。但用户提交的“富文本“数据语义是完整的HTML代码,在输出时也不会拼凑到某个标签的属性中。因此可以特殊情况特殊处理。上一节已经列出来了所有在HTML中可能执行脚本的地方。而一个优秀的XSS Filter也应该能找到HTML代码中所有可能执行脚本的地方。HTML是一种结构化的语言,比较好分析,通过htmlparser可以解析出HTML代码的标签、标签属性和时间。

1.在过滤富文本时,“事件”应该被严格禁止,因为富文本的展示需求里不应该包括事件这种动态效果。而一些危险的标签<iframe>、<script>、<base>、<form>等,也是应该严格禁止的。

2.在标签的选择上应使用白名单原则,避免使用黑名单(二者之区别在《安全方案的设计原则笔记》 blog.csdn.net/Yisitelz/article/details/131985322)。只允许<a >、<img>、<div>等比较安全的、能把握得住的标签存在。白名单原则不仅仅用于标签的选择,同样还应该用于属性和事件的选择。

3.处理XSS也是一件麻烦的事情。如果允许用户自定义CSS、style,则也很可能导致XSS攻击,故应尽可能禁止用户自定义CSS和style。任意一定要允许用户自定义样式,则只能像过滤“富文本”一样过滤CSS,这有需要一个CSS Parser对样式进行智能分析,检查其中是否包含危险代码。

防御 DOM型 XSS

DOM型XSS比较特别,前面提到的几种防御方法都不太适用,需要特别对待。

DOM型XSS咋产生的?再看看这个例子

这将HTML代码写入了DOM节点,最后导致了XSS的发生。

事实上DOM型XSS是从JavaScript中输出数据到HTML页面里。前面提到的方法都是针对“从服务器输出到HTML页面”的XSS漏洞,因此并不适用于DOM型XSS。再看看下面这个例子。

 

原因就在于第一次执行javascriptEscape后只保护了

当document.write输出数据到HTML页面时,浏览器重新渲染了页面,<script>标签执行时,已经对变量x进行了解码,其后document.write再运行时,其参数就变成了

XSS攻击由此产生。

那是不是因为对于$var用错了编码函数呢,换成HtmlEncode会怎么样?继续看这个例子:

服务器把变量HtmlEncode后再输出到<script>中,然后变量x作为onclick时间的一个函数被document.write 写到了HTML页面里。

 那么正确的防御方法是什么呢?

首先,在”$var”输出到<script>时,应该执行一次JavaScriptEncode;其次,在document.write输出到HTML页面,要分具体情况看待:如果是输出到事件或者脚本,则要再做一次javascriptEncode;如果是输出到HTML内容或者属性,则要做一次HtmlEncode。也就是说,从JavaScript输出到HTML界面也相当于一次XSS输出的过程,需要分语境使用不同的编码函数。

容易出现DOM型XSS的地方:

  • document.write()
  • document.writeIn()
  • xxx.innerHTML =
  • xxx.outerHTML =
  • innerHTML.replace
  • document.attachEvent()
  • window.attachEvent()
  • document.location.replace()
  • document.loation.assign()

等等等等

除了服务器端直接输出变量到JavaScript外,还有以下几个地方可能会成为DOM型XSS的输入点,也需要重点关注。

  • 页面中所有的input框
  • window.loaction(href、hash等)
  • window.name
  • document.referrer
  • document.cookie
  • localstorage
  • XMLHttpRequest返回的数据

参考资料:《白帽子讲web安全》吴瀚清

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值