X

曜彤.手记

随记,关于互联网技术、产品与创业

WebAssembly 深入研究报告 - 安全性

每个 WebAssembly 模块都会在自己独立的沙盒环境中执行导出的函数和代码。这个独立的沙盒环境通过一些错误隔离技术将 Wasm 的运行环境从主机的运行时环境中隔离出来。不仅如此,每一个 Wasm 模块的运行也同样会首先遵循其所在平台环境的安全策略。比如运行在 Web 浏览器中则会遵循同源策略,而在非浏览器环境则一般会遵循 POSIX 安全模型。

Wasm 通过减少其语义中较为危险的特性,并同时保持对 C/C++ 在语法上的最大兼容性来保证一个较高的安全性和可用性。模块必须在加载时声明所有可访问的方法和它们的相关函数签名类型,包括用到的动态链接函数。这样做的好处是可以在程序运行过程中隐式地通过 CFI 来检查应用程序是否被劫持。CFI 在运行时检测程序的控制转移是否在控制流图(CFG)中,以识别是否遭遇了攻击。具体作法是在控制流转移指令前插入检验代码,来判断目标地址的合法性。这种做法能够对控制流劫持攻击起到防御作用。同时,编译好的代码由于不可以被修改,也不会在运行时被观测到,因此可以完全避免受到控制流劫持攻击。下面给出一些规则。

  1. 函数调用必须指定与函数索引空间或表索引空间中的有效条目相对应的目标索引。函数索引空间索引所有导入和内部定义的函数,根据模块中的定义顺序(由二进制编码定义)分配递增的索引值。因此,索引空间的索引值从零开始,先索引导入的函数,接下来是模块中定义的函数。表索引空间与函数索引空间基本相似;
  2. 间接的函数调用需要在调用时指定目标函数的类型签名,两者必须要完全一致函数才可能被调用。详见文章:《WebAssembly 尝试研究报告 - API 之初始化、内存和表的分配》;

C/C++ 中的所有变量都可以根据其作用域范围被“降级”为 WebAssembly 中对应的两种原始类型 — 局部变量和全局变量。局部变量有着固定的作用域,全局变量是有固定类型的值,并且通过索引进行存储。在默认情况下,局部变量被初始化为零并存储在受保护的调用栈中,全局变量位于全局索引空间中,可以从外部模块中导入。对于那些静态变量作用域不明确的局部变量(比如被用于取地址符的变量,或是以值传递的结构体类型)在编译时会被存储在线性内存上一个单独的用户可寻址堆栈中。这是一个独立的内存区域,它具有固定的最大地址空间,默认初始化情况下的大小为0。




评论 | Comments


Loading ...