介绍

正如我们最近所解释的那样,WebAssembly 是一种二进制格式,适用于用任何语言编写的软件,其最终目标则是在任何平台上运行而无需更改。WebAssembly 的首次应用是在网络浏览器内,使网站更快、更具互动性。此后,WebAssembly 被推向 Web 以外的领域,从各种服务器到物联网(IoT),创造了很多机会,也带来了很多安全问题。这篇文章是对这些问题和 WebAssembly 安全模型的介绍性概述。

WebAssembly 就像 JavaScript

在网络浏览器内,WebAssembly 模块由执行 JavaScript 代码的同一虚拟机(VM)管理。因此,WebAssembly 也可以被用来执行许多与 JavaScript 相同的恶意指令,而且 WebAssembly 更有效,并且更不明显。由于 JavaScript 是浏览器会编译的纯文本,而 WebAssembly 是一种随时可以运行的二进制格式,所以后者运行速度更快,也更难被扫描出(即使是杀毒软件)恶意指令。

WebAssembly 的这种"代码混淆"效果已经被不法分子所利用,其中包括弹出不需要的广告,或者打开假的"技术支持"窗口并要求提供敏感数据。另一种伎俩是将浏览器自动重定向到包含真正危险的恶意软件的落地页面。

最后,WebAssembly 可能会像 JavaScript 一样,被用来"窃取"设备的处理能力而不是数据。2019年,对 150 个不同的 Wasm 模块进行分析后发现,其中约 32% 的模块被用于挖掘数字货币。

WebAssembly 沙盒以及接口

WebAssembly 代码在虚拟机管理的沙盒中封闭运行,而不是由操作系统管理。这使得它无法看到主机,也无法直接与主机交互。对系统资源的访问,无论是文件、硬件还是互联网连接,都只能通过该虚拟机提供的 WebAssembly 系统接口(WASI)来实现。

WASI 与其他大多数应用编程接口不同,具有独特的安全特性,这也是真正推动 WASM 在服务器/边缘计算场景中应用的原因。在这里我只想说,当从 Web 转移到其他环境时,它的安全影响大不相同。现代的网络浏览器是非常复杂的软件,但它是建立在几十年的经验和数十亿人的日常测试之上的。与浏览器相比,服务器或物联网设备几乎是一片未知的土地。这些平台的虚拟机将需要 WASI 的扩展,因此,肯定会反过来引入新的安全挑战。

WebAssembly 中的内存和代码管理

与普通的编译程序相比,WebAssembly 应用程序对内存的访问非常受限,对自身的访问也是如此。WebAssembly 代码不能直接访问尚未被调用的函数或变量,不能跳转到任意地址,也不能以字节码指令的方式执行内存中的数据。

在浏览器内部,一个 Wasm 模块只能得到一个连续字节的全局数组("线性内存")。WebAssembly 可以直接读写该区域的任何位置,或者请求增加其大小,但仅此而已。这个线性内存还与包含其实际代码、执行栈的区域分开,当然还有运行 WebAssembly 的虚拟机。对于浏览器来说,所有这些数据结构都是普通的 JavaScript 对象,使用标准程序与其他所有对象绝缘。

结果是:不错,但不完美

所有这些限制使得 WebAssembly 模块用于恶意行为变得相当困难,但并非完全不可能。

沙盒式的内存,使得 WebAssembly 几乎不可能接触到外面的东西,也使得操作系统更难防止内部发生坏事。传统的内存监控机制,比如"stack canaries"在这里却无法正常工作,该机制可以注意到是否有代码试图去接触那些不应该接触的对象。

事实上,WebAssembly 只能访问自己的线性内存,但直接访问,也可能为攻击者的工作提供便利。有了这些限制条件,再访问模块的源代码,就可以更容易地猜测哪些内存位置可以被覆盖,从而做出最大的破坏。破坏局部变量似乎也是可能的,因为它们停留在线性内存的无监督堆栈中。

一般来说,认为 WebAssembly 只能破坏自己沙盒内的东西的想法可能会产生误导。WebAssembly 模块为调用它们的 JavaScript 代码做着繁重的工作,每次都会交换变量。如果他们在这些变量中写入任何可能导致调用 WebAssembly 的不安全 JavaScript 崩溃或数据泄露的代码,这些事情就会发生。

前方的路

WebAssembly 的两个新兴特性肯定会对其安全性产生影响(如何影响、影响多大,现在还为时过早),那就是并发和内部垃圾收集。

并发就是允许多个 WebAssembly 模块同时在同一个虚拟机中运行。今天,这只能通过 JavaScript Web worker 实现,但更好的机制正在开发中。安全性方面,它们可能会带来"很多以前不需要的代码......",也就是更多的出错方式。

虽然需要一个原生的 Garbage Collector 来提高性能和安全性,但最重要的是要在浏览器经过良好测试的 Java 虚拟机之外使用 WebAssembly,反正自己内部的垃圾都会被收集起来。当然,即使是这种新的代码,也可能成为另一个 bug 和攻击的入口。

从积极的一面来看,仍然存在着让 WebAssembly 比现在更安全的通用策略。

04-01 18:29