Web 2.0 早已不是什么新话题。过去的几年内,知名度高如 Google、Yahoo、MySpace、PayPal 等大站,也都无法完全免疫,而陆续爆发过各种攻击事件(钓鱼、虫…)。Web 2.0 网站不管是选择用 AJAX 、Flash,还有逐渐风行的离线解决方案,如 Dojo Offline、Google Gears 、Adobe AIR 等,来提供互动性更高的 UI,只要一不小心,这些 Web 应用出现安全漏洞、被坏人占便宜的机率,其实是很高的。有时候不仅是自己的 code,而问题也可能出现在第三方提供的现成工具箱、API。
要如何防范?对网站开发人员而言,在过去,对这个主题的探讨,往往比较零散,要不就偏学术,要求较高的门槛(例如 OWASP 发表的文献),一直缺乏系统化,全面性,且深入浅出的探讨。不久前终于出了一本好书 — AJAX Security,作者为 Billy Hoffman 和 Bryan Sullivan 这两位 Web 2.0 安全的专家(过去在零星的安全相关报道中,也常出现他们两位的影子)。在此强烈推荐这本书,给所有从事与 Web 2.0 开发相关的网友。尽管书名选择叫 "AJAX" Security,但事实上,除了 AJAX 之外,Flash 安全,甚至于如何将 CSS 这种看似无害、展现层的东西,拿来攻击的方法,在书中都有深入探讨(第十二章)。尽管这样的书,早该出现,但出版时间晚,反而也做出一些额外的贡献 — 比较新的科技,如上述的 Google Gears 和 Dojo 离线工具箱的安全弱点,在书中都涵盖了。希望它尽快能被翻译成中文,以造福更多大众。
真的有那么可怕吗?如果你问作者,那么他的答案,会是一个非常肯定的 "YES!!",这么说只是因为他想多卖几本书吗?其实不是。不管从书里,或从这个和作者的 podcast 访谈中,作者列举的种种弱点,攻击方式,技术上都论点铿锵,绝非危言耸听。而最恐怖的还是,各大著名网站相继中箭的事实,为这些攻击方式,提供了最佳的 “成功案例”。这些安全事件,听在不懂技术的一般网民耳中,如果再被过分渲染,往往会引发“因噎废食”的反应(英文叫 "knee-jerk reaction")。记得多年前 Web 1.0 时代,许多用户便对 cookies 有不明就里的惧怕。身为 IT 从业人员的我们,自然不希望用户采取过当的对应手段,例如选择将浏览器中的 JavaScript 关闭(那将会是 Web 2.0 最黑暗的一天)。但我们也的确要好好警惕,让对我们网站的攻击事件的发生机率,尽量减到最低 — 这点更凸显了本书的重要性。
如果 Web 2.0 安全也有“十戒”般的戒律,那么第一大戒肯定是:绝对不能相信 client 端。来看作者在 podcast 中所举的一个很经典的例子,他们还因此吃了很多免费的汉堡
。故事是这样的:美国的麦当劳网站上,有个用 Flash 开发的棋盘游戏,赢的人可得到免费的兑换餐券。他们先用 sniffer 检视浏览器对外的交通,发现这个 Flash 游戏不断需要对某个网站传递信息,因此怀疑程序的作者可能将游戏的输赢状态,直接向某个 Web service 回报(这已经犯了另一戒 — 不该将程序的状态控制或流转逻辑放在 client 端,因为 client 端是不可信赖的)。他们发现拦截到的信号是一些奇怪的乱码,但看起来又不像是用 SSL 加密过的 pattern。于是接着开始将 Flash 程式 SWF 进行反编译(用的是 Flare,一个 open-source 的 SWF 反编工具)。从源代码中,分别找到一个负责加密、一个解密的函数 — 啊哈!原来用的是一个对称性加密演算法(又犯一戒 — 因为应该用不对称加密,即 public-key encryption),这代表在程序中某处,必藏有那把加解密都需要的私钥。果然,作者不但找到、伪造了对服务器端回报结果的请求,而且还根据该 key 的命名 pattern("某设计公司_客户_3"),推测出承包麦当劳网站的那家设计公司,所承包的其他网站中,也有类似的做法。果然,他们去看该设计公司的客户列表,得知是那些网站,然后用 "…_客户2"、“…_客户5” 诸如此类的 key,也成功地破解其他网站的游戏,赢得更多奖品。
关于如何过滤用户输入的问题,作者也提了一些很好的建议。一是用黑名单方式 (blacklisting) 的不足,建议实在应改用白名单来过滤 (whitelisting)。我们知道,黑名单的过滤方式,是针对已知的不正常字元、字串 patterns 等进行过滤,以避免包括 SQL 注入、JavaScript 注入等的攻击,如果黑名单漏了任何其他的可能,攻击仍可能成功。相对地,白名单则更加严格,只让合理的内容通过(例如电话号码的栏位,只可能有数字、“+”、“-”、"("、“)”、空白这几种可能的字元),任何其他,不管是不是特殊字元,一律挡掉。
此外,光是在浏览器端用 JavaScript 过滤用户的输入是不足的(因为第一戒:不可相信 client),server 端的过滤相形之下更加重要。当然,这个需求会增加不少开发人员的负担,要如何将过滤的条件在 server 和 client 间同步?实现方式?未来随着 Dojo、Google Gears、Adobe AIR 这类的离线应用的普及化,如果要确保安全,每当离线的 client 恢复和 server 的联系,就要检查一次,这个过滤条件同步工作只会更加复杂。
Google Maps 的成功,可说带来了 mashup 的大量风行。例如某 blog 网页,希望在用户访问该 blog 时,同时可以动态从几个第三方网站,如 Google、del.icio.us 等拿数据,内嵌在 blog 网页中,这是典型的 client 端 mashup,不需要 coding,只需剪贴几行简单的 JavaScript 到网页模板里即可。此类 widgets、gadgets 在众多社交网站的用户首页中,早已获得爆炸性的欢迎。但事实上,在 Google、Yahoo 和众多供应商提供这些简单、高生产力的 API 背后,牵涉了一个叫 “同源政策” (Same Origin Policy) 的技术障碍,需要绕过。简单地说,按照 Firefox、IE、Safari 这些支持 AJAX 浏览器先天的安全设计,JavaScript 到上述例子中的 blog 网之外的其他网站去下载数据,是不被允许的,就像 JavaScript 不可跨域读 cookies 一样。Google、Yahoo 的工程师很聪明地利用了 JSONP(JSON with Padding,或称 JSON RPC),设计出一个 “跨站脚本运行”(Cross-Site Scripting,简称 XSS)的解决方案(注)。JSON 的运用,成就了 mashup,但在此同时,许多此类的程序,也暴露出可被人进行注入式攻击的漏洞。例如过去 Gmail 的 JSON 程序,就被人用来窃取通讯录的内容。Google 还有其他好几个服务,都曾经成功地被人用 JavaScript 注入攻击。
Flash 的跨域 XML (cross-domain XML) 对象,也是一个潜在的问题。作者提到 Flickr 的 SWF API 中,用了跨域 XML,暴露出让人有机可趁的弱点。
是不是有什么方便的工具,可以将大部分安全检查的工作自动化?作者现身说法,以自己过去曾创立过一家小公司长期研发此类工具的经验,悲观地表示,由于问题牵涉的复杂性,很难做出能高度自动化的工具。目前最有效的方式,还是通过对开发人员的教育。说到开发人员的背景,作者表示自己在近两年,体会到一个遗憾的趋势(主要指美国) — 有愈来愈多非 Web 程序员出身的开发人员,其中许多有多年 C/S 应用开发经验,认为 Web 开发很简单,没什么大不了的,因此不太能接受他人关于 Web 安全方面的忠告,他们忽略了 Web 的应用模式和过去他们熟悉的那些有很大的不同,因此安全方面的顾虑也大不同。当然,广大 Web 开发人员中还有很多是从网页设计工作慢慢接触 scripting 的,尽管他们相对而言非常虚心学习,但因为本身的技术背景有限,可能会对复杂的安全问题感到头大而不知从何下手。作者说到尽管自己是 CS 科班出身,但过去学校也并未对安全这门知识,有任何系统化的教育,他的知识都是后来自学的。这些都加深了问题的严重性。
如果把上述的安全问题放到 SOA 和企业 Web 2.0 的上下文中,不难预见,将产生一些新的挑战。在 SOA 界地位颇高的资讯机构 CBDI,他们的总经理兼首席顾问 David Sprott 在三月份的期刊中,对服务组装 (Service Assembly) 的发展现况和展望,做了一个探讨(需要注册)。他认为在各种现行方式均不尽理想的情况下,AJAX mashup 的简单方式,提供了一个新希望。但他同时也承认,有安全上的顾虑需要面对。
试想:如果未来某大上市企业,开始在内部开放一些 JavaScript 的 API,让员工可以自由地做 mashup,是不是有可能发生某员工利用该 API 有可以让人进行 JavaScript 注入的漏洞,布置一个钓鱼攻击,骗到某 CXO 的密码,用以登录财务系统,偷看下次财报的相关资料,事先进一批股票海削一笔?这不是天方夜谭。
注:
- XSS 里的 X 像斜躺的十字架,所以老美就用 X 作为 "cross" 的缩写,记得刚到美国的时候,常见许多 "XING" 的路标,不知是什么意思,后来才知道代表 crossing,警告前面可能有火车、行人、野生动物等穿越
- JSONP XSS 的运作原理:一,二。