前段时间,Apache Struts2又接连曝出了两个高危远程代码执行(Remoce Code Execution,下文简称RCE)漏洞(CVE-2017-5638)。为什么要说“又”呢?那是因为这早就不是Apache Struts2第一次曝出这类漏洞了。
你应该还有印象,早几年前Apache Struts2披露了一系列RCE漏洞,而且他们家在披露RCE漏洞的同时还附带了证明漏洞存在的POC(Proof Of Concept)脚本。在那次事件中,由于POC包含的信息量太大,其本意可能是想方便开发者了解更多漏洞细节,但未曾想却为黑客攻击提供了重要线索,不得不让人觉得是“神助攻”。再加上,这种做法几乎就没给使用Struts2的开发团队留出进行修复的时间,以至于在短时间里,国内外众多使用Struts2的网站,包括一些知名网站均遭到黑客攻击,大量网站纷纷表示躺枪。
如果说现如今Struts2在新开发的应用中的使用量小到几乎可以忽略不计,它的安全漏洞所带来的影响有限,那么当下火爆的各种前端JavaScript开发框架、库当中也存在安全漏洞这一事实却让情况变得不容乐观。
早在2014年,当时的一份调查研究发现,在Alexa排名前10万的网站中,有60%的网站使用了至少含有一个已知安全漏洞的JavaScript库。时间来到2017年,美国波斯顿Northeastern University做了一次跟进调查,发现Alexa排名前13万的网站中,有37%的网站使用了至少含有一个已知安全漏洞的JavaScript库。
使用含有已知安全漏洞的第三方组件的现象为何会如此普遍呢?原因是多方面的,比如,在采用第三方组件的时候没有对其进行安全检查,或者最初该组件并没有安全漏洞,只是随着时间推移,一段时间后被发现存在安全问题并披露了出来,等等。要想扭转这一局面,开发团队却也面临着不小的挑战。
挑战一:第三方组件及其版本号众多,需要快速确认哪些存在已知安全漏洞,是否受到漏洞披露的影响
无论是服务器端应用还是运行在浏览器里的前端应用,使用几十个第三方组件、库是稀疏平常的事情,更何况这还只是直接依赖的第三方组件,要是算上间接依赖(即第三方组件所依赖的第三方组件,以此类推)的话,组成一个应用的第三方组件数量将会相当可观。
在知道应用所使用的所有第三方组件之后,还需要知道各个组件的精确版本号,然后才能将组件、版本号在已知漏洞数据库里进行匹配查询,得出最后的结果。
让问题变得更加棘手的是,一个企业里往往有不止一个应用系统,而每个系统都需要定期或者不定期的做这样的排查,所需要的工作量有多么巨大可想而知。
挑战二:和时间赛跑,需要在第一时间内得到通知,以最短时间完成修复和测试,并发布到生产环境
应用在还未发布时如果遇到这类问题,开发团队有充足的时间来做出应对,但对于已经处于运营中的应用而言,时间就是生命线,这是一场和黑客争分夺秒的战争,如果不能赶在黑客进行攻击前完成修复、发布等一系列任务,那就只能祝你好运了。
挑战三:对企业持续交付能力是个考验
在第三方组件的提供商披露安全漏洞的同时,还会给出修复建议,而通常的情况是,开发团队只需要将受到影响的第三方组件升级到新版本即可。看上去这似乎一点不难,但却细思极恐。
第一,版本升级可能会带来兼容性问题,导致应用无法正常启动、使用等。解决兼容性问题就可能得花去不少时间。
第二,迈过了兼容性这一关,开发团队还得对应用进行回归测试,以确保版本升级没有破坏原有的业务功能。那么问题来了,你的团队需要花多少时间进行这一测试呢?几分钟?几小时?还是几天甚至几周?
第三,开发团队排除重重困难,避开了兼容性问题,完成了回归测试,终于走到了发布修复这一步。此时,你的团队是否能对应用进行蓝绿部署、滚动发布以保证生产环境业务不会因为部署而中断?
创建和维护第三方组件信息库
开发团队可以将应用中所使用到的所有第三方组件,包括那些间接依赖的第三方组件,及其版本号集中收集起来,形成一个组件信息库。于是,每当有第三方组件安全漏洞信息披露出来的时候,开发团队都可以立即做出判断,了解自己的应用是否受此次漏洞披露的影响。
定期匹配排查
除了在得到第三方组件安全漏洞的信息披露通知后进行识别判断,开发团队还非常有必要主动的对所用到的组件进行定期安全检查。因为在上一步中已经识别出了所有的第三方组件及其版本号,开发团队接下来需要做的,是将这些信息在已知安全漏洞数据库(例如National Vulnerability Database)中进行匹配。
自动化
刚才已经提到,识别第三方组件及其版本号,并且还要对其进行细致的匹配排查,工作量是非常巨大的,如果没有自动化的帮助,仅仅依靠人工的话,几乎是不可能完成的任务。
幸运的是,目前已经有不少工具能帮我们完成这一工作,例如两次入选ThoughtWorks技术雷达的OWASP Dependency Check,它能自动完成第三方组件识别、漏洞数据库维护,以及漏洞匹配、生成检查报告等一些列活动。除了支持Java和.Net应用外,还支持Ruby、NodeJS以及Python应用,以及部分C/C++应用。
同类型的工具还有支持.NET的OWASP SafeNuGet,专门针对Node应用的Node Security Project等等。对于其他语言,也有各自对应的自动化检查工具,在此就不一一列举了。
贯穿整个生命周期
在应用开发过程中,第三方组件可能会不断的被加入到项目里,或者移除出去,其版本也可能会随着时间的推移而不断更改。在这个过程中,组件的的每一次变化都可能会带来新的安全隐患。
开发团队可以利用上一步提到的自动化检查工具,并将其和CI服务器集成起来,可以很容易做到在每次代码提交的时候进行一次安全检查,从而达到持续监控组件安全性的目标。
应用往往使用了大量第三方组件,它们可能含有安全漏洞,给应用的整体安全性埋下隐患。开发团队和黑客一直都在进行时间竞赛,其必须要在第一时间内得到安全漏洞的披露通知,赶在黑客发动攻击之前,完成漏洞修复工作。
好在开发团队可以利用各种自动化工具,快速且全面的发现那些有问题的第三方组件,通过运行回归测试以确保原有业务行为的正确性,并且结合持续交付的能力,在不影响生产环境业务持续运行的情况下,将代码改动发布到生成环境,及时避免第三方组件安全漏洞给应用带来安全风险。
文/ThoughtWorks 马伟
注:文中参考资料部分,可在原文中查看:http://t.cn/RT4cJuG