软件安全的一场“极左”革命:安全编程语言
用Rust开发代码不仅能避免很多常见的安全漏洞类型,而且最终会对全球网络安全基线产生重大影响。
今天,无论是大型企业的IT系统还是个人的智能手机,都面临无休止的补丁更新,因为这些系统中的软件每天都会暴露不同的缺陷和安全漏洞。
人们似乎已经被迫接受了这样两个简单的“宿命”:
- 是人就会犯错,所以代码漏洞不可避免;
- 软件开发的安全性、效率和成本三者不可兼得。
但是,一种名为Rust的安全编程语言正在快速崛起,逆转软件安全的宿命。
在程序员中最流行的计算机编程语言榜单上,Python、Java、C++、C、JavaScript和C#常年霸榜,但是Rust已经成为增长最快的编程语言:
在软件安全的“左移”运动中,编程语言位于软件开发生命周期的最左侧,我们不妨称之为软件安全的“极左革命”。用Rust开发代码不仅能避免很多常见的安全漏洞类型,而且最终会对全球网络安全基线产生重大影响。
“自带安全属性”成为引爆点
编程语言就像时尚秀场,你方唱罢我登场,很多红极一时的语言最终只落得昙花一现。但12岁的Rust却表现出越来越强大的生命力,已经从Mozilla研究人员的副项目成长为一个强大的生态系统。
Rust的流行并非偶然,其承上启下,兼具现代性和工程友好的特性,以及性能与安全兼得的优点,都让Rust有了不可估量的前景。Rust的“自带安全属性”正获得越来越多的开发者甚至硅谷巨头的青睐,如今已经到了一个“引爆点”,对于软件工程和软件安全来说都意味着一场革命。
自2019年以来,微软、谷歌和亚马逊网络服务一直在使用Rust,这三家公司于2020年与Mozilla和华为成立了非营利性Rust基金会,以支持和发展该语言。经过数年的不懈努力,Linux内核上个月取得重大突破:实现了对Rust的支持。
“Rust正在快速流行,”Android(安卓系统)安全和隐私工程副总裁Dave Kleidermacher透露:“我们一直在Android和整个Google产品线上投资Rust,很多工程师都在考虑如何上车。随着Rust首次登陆Linux并成为官方认可语言,不仅仅是Android,现在任何基于Linux的系统都可以开始集成Rust组件。”
Rust最大的亮点之一是“自带安全属性”,属于一种“内存安全”语言,其原生安全设计能够防止程序意外地从计算机内存中提取数据。当程序员使用没有此安全属性的主流语言(包括C和C++)时,必须仔细检查程序将请求哪些数据,以及如何请求的参数。即使是经验最丰富的开发人员也会偶尔疏忽犯错。而如果使用Rust开发软件,即便是菜鸟程序员也不用担心会在代码中引入任何内存安全错误。
程序调用的内存中包含其所有功能和库所使用的共享资源。例如,当你打开一个非内存安全语言开发的日历程序,然后查询2022年11月2日的日程信息,程序会从分配给存储该日期数据的计算机内存区域中获取所有信息,这一步没什么问题,但是当你请求2022年11月42日的数据时,如果程序设计没有正确约束,不但不会报错,反而会尽职尽责地从内存中存储其他数据的地方返回一些意想不到的信息,例如你为日历设置的密码,或者在日历高级功能中存档的信用卡号。同样,如果你添加一个11月42日的生日派对日程,程序不会告诉你无法完成任务,而是可能会覆盖内存中不相关的数据。这类错误被称为“越界”读写错误,显然,这种错误可被攻击者被利用非法访问数据,甚至扩大系统控制权限。
另一种常见的内存安全错误类型是“释放后使用”,即当程序释放部分内存后(例如你删除了2022年10月的所有日历条目)但错误地保留访问权限(指针并未删除)。当你稍后请求10月17日的数据时,该程序可能仍然能够抓取到(10月份的)数据。软件代码中此类内存安全漏洞可被黑客利用制作恶意日历邀请,其中包含精心挑选的日期或一组事件的详细信息,旨在操纵内存以授予攻击者远程访问权。
安全研究和审计反复证明,大多数软件漏洞属于内存安全类漏洞。因此,虽然在Rust中编程时开发者仍然可能会犯错误并产生安全漏洞,但有很大机会杜绝内存安全漏洞。
“内存安全问题占所有报告漏洞的很大一部分,尤其是操作系统,手机和基础设施等关键应用程序,”软件供应链安全公司Chainguard的首席执行官Dan Lorenc指出:“几十年来,人们一直在用内存不安全的语言编写代码,我们试图改进和开发更好的工具,并教人们如何避免这些错误,但仅仅靠鞭策来加强安全性是不够的。我们需要一种新技术,从根本上消灭漏洞,这就是Rust最终带来的(希望)。”
Rust面临的挑战与机遇
Rust并不缺乏怀疑者和批评者。过去两年在Linux中实现Rust的努力一直存在争议,部分原因是添加对任何其他语言的支持本身会增加系统的复杂性,还有一些是关于如何使Rust在Linux中正常工作的争论。但支持者强调Rust满足了几个重要条件:不会导致性能损失,与其他语言编写的软件具有良好的互操作性,而且它满足了迫切的需求。
“与其说这是正确的选择,不如说我们别无选择,”资深开源贡献者和研究员Lorenc说道:“除非什么都不做,否则Rust就是唯一选择。未来十年继续使用内存不安全的代码将给科技行业,国家安全和数字经济的每个角落都留下重大隐患。”
然而,过渡到Rust的最大挑战之一恰恰是开发人员已经花费了几十年的时间,用内存不安全语言开发的重要代码。用Rust编写的新软件短时间还无法撼动海量的现存软件代码。例如,Rust在Linux内核的实现是从外设——基于Rust的驱动程序开始的,这些驱动程序负责在操作系统和打印机等硬件之间进行协调。
“当你做操作系统时,速度和性能总是头等大事,过去,当你用C++或C而不是用Java或其他内存安全语言运行的部分,是出于性能方面的考虑,”谷歌的Kleidermacher说:“但Rust能提供相同的性能,同时又获得内存安全性,这真的很酷。但这需要一个过程。你不能在一夜之间重写5000万行代码,所以我们正在仔细挑选安全关键组件,随着时间的推移,我们会改造其他东西。”
Kleidermacher指出:在Android中,已经有许多加密密钥管理功能都是用Rust编写的,包括HTTPS上的私有互联网通信功能DNS,超宽带芯片堆栈的新版本,以及Google定制Tensor G2芯片中使用的新Android虚拟化框架。Android团队越来越多地将蓝牙和Wi-Fi等连接堆栈迁移到Rust,因为它们基于复杂的行业标准,并且往往包含大量漏洞。简而言之,Google采取一种渐进式安全策略,首先将最重要和暴露最多的软件组件转换到Rust,然后“内卷”到其他代码,逐步获得增量安全收益。
“是的,这需要大量工作,但科技行业的价值数以万亿美元计,拥有数不清的优秀程序员,有足够的资源推动此事。”互联网安全研究小组执行董事Josh Aas说道。该组织负责内存安全倡议Prossimo以及免费证书颁发机构Let’s Encrypt。
随着Rust进入主流应用,很多困扰业界多年的内存安全问题都有望得到解决。例如上周让全球安全人士焦虑的OpenSSL漏洞,如果OpenSSL是用内存安全语言编写的,那么其中至少一个高危漏洞就可避免。与2014年臭名昭著的OpenSSL漏洞Heartbleed(心脏滴血)不同,上周修复的漏洞潜伏了两年之久,导致网站受到数据拦截攻击。虽然OpenSSL一直在努力减少内存安全漏洞,但在几个月前,这个新漏洞还是被引入了OpenSSL3.0.x新版本中。
参考链接:
https://www.wired.com/story/rust-secure-programming-language-memory-safe/