在去年年底的时候,我曾经写过一篇关于对抗XSS Worm的文章,发在了幻影以前的blog上。(站点是放在blogspot上的,目前被和谐了,使用国外代理可以访问)
其中主要提到了这么几点防御措施
1. 断其源头(修补XSS漏洞)
2. 检查所有用户之间发生交互的地方
3. 使用验证码或者密码来验证重要应用流程
4. 使用一个处于比较核心位置的功能来阻断连续提交
5. 完善的log机制
6. 法律需要进一步完善
但是,在实际操作起来的时候,可能会遇到比较大的阻力。
比如
XSS漏洞太多了,成千上万,无从入手
网站内部逻辑复杂,连开发者都说不清里面的调用关系
项目文档只有流程图,没有数据流图
加验证码会影响用户体验
等等
其实,我认为最困难的还是两点:
1. 大量的XSS漏洞导致一种无从下手的感觉
2. 无法遍历所有用户发生交互的地方
这两点都不是技术原因造成的,技术困难是可以解决的。而这两点往往是其他因素造成的困难。
今天80sec放出了一个CSRF蠕虫,是一种非常值得注意的攻击形式,所以,XSS WORM的防御中,应该加入针对CSRF WORM的防范。
我们在防御CSRF的时候,往往是采用给link或者form里加随机token的做法,在浏览器提交后,服务器验证token的一致性以判断请求是否合法。
但是程序员肯定不会同意给所有的link和表单都加上token,所以一般是只有重要的操作才会加上token。什么才叫重要的操作?删除、插入等都应该属于重要操作,但是在这里为了不偏题,先不讨论怎么定义“重要”二字,先看看在CSRF WORM中,应该如何防范。
如果用最低的代价防御XSS/CSRF WORM的方法,应该这样做:
找到可能引起WORM的入口,然后修补该入口的XSS、CSRF。
把网站的应用看做是一个完整的系统,网站对用户提供种种功能,而用户通过向网站提交数据来与网站发生交互。
这一个过程简单描述如下:
对于WORM来说,最容易利用的入口,就是发生用户交互的地方。这些地方,对于XSS WORM来说是stored 类型的XSS,CSRF也差不多。
在这里,我把用户提交的数据,也就是INPUT分为3类:Public、Private、Share
Public,也就是公共数据,任何人都可以看到,比如一篇新闻,发表的评论,就属于这种数据
Private,私有数据,只有用户自己本人能看到,别人看不到。大部分的反射型XSS,提交的数据都应该归类到这里。
Share,共享数据,部分用户能看到。比如给自己的好友发短消息,这个短消息就属于共享数据。
所以,根据这个分类,在一般情况下,应该优先考虑用户能够控制的 Public 和 Share 数据,大部分的worm都是依赖于这两类数据而发起的。
在实际应用的时候,应该在SDL流程中,威胁建模阶段,根据简单的数据流图,审计出用户提交的数据哪些是 Public的、Share的。对于这类型的数据,需要重点审核,因为这类数据发生的问题的风险,是要高于private类数据发生问题的风险的。
为什么要做这种分类?为什么要在INPUT检查这种分类?因为在OUTPUT再检查数据分类是不太现实的,数据经过应用内部多个逻辑,很难判断出其中某一个逻辑环节是否可以被用户控制,即便你的数据是从数据库里取出来的,也有可能被影响。
所以我们面临的新的挑战是,如何在SDL中好好的落实这种针对分类数据的检查!