[RSCH] 13 分鐘閱讀OraCore 編輯部

Bento 把 Wasm 記憶體切成隔間

Bento 用 WebAssembly multi-memory 把高風險資料切開,讓既有 Wasm 二進位更難被 buffer overflow 連坐。

分享 LinkedIn
Bento 把 Wasm 記憶體切成隔間

Bento 用 WebAssembly 的多記憶體把高風險資料切開,讓既有 Wasm 二進位更難被 buffer overflow 連坐。

我盯 WebAssembly 安全這題很久了,老實說,劇本一直都差不多:大家把 native-ish 的程式搬進瀏覽器,然後又假裝舊世界的記憶體爛帳不會跟著搬進來。最煩的就是這裡。Demo 跑得很順、載入也快,但只要一個 bounds check 寫歪,整個瀏覽器內的資料就可能一起遭殃。我看過不少團隊想靠重寫原始碼、加 runtime hardening,或是搞一套只能在實驗室跑的瀏覽器設定來補洞,結果一到要真正發佈就卡死。

所以我看到一篇文章在講「不要重寫 app,直接自動重整記憶體」時,我就停下來了。這種說法比較像真的能落地,而不是安全圈常見的自我感動。WebAssembly 原本的賣點就是把嚴肅軟體帶進瀏覽器,少掉安裝麻煩,不是逼每個供應商都去做一輪安全重構馬拉松。這裡真正有意思的,不是記憶體安全重要,這大家都知道;而是研究者想在編譯後、二進位層級,把問題拆開處理,還要讓使用者感覺不到差別。

這篇拆解的觸發點,是 TechXplore 在 2026-06-05 的文章 New WebAssembly memory layout could stop Heartbleed-style browser attacks with no visible slowdown,它整理了 University of Duisburg-Essen / paluno 的 Oussama Draissi 與 Prof. Lucas Davi 的工作。對應的論文是 Bento: Fine-Grained Memory Isolation for COTS WebAssembly Binaries。核心很直白:他們用 Wasm 的 multi-memory 特性,把危險資料隔開,而且不需要原始碼或特殊硬體。

問題不在 WebAssembly,而在舊記憶體 bug 換了新包裝

訂閱 AI 趨勢週報

每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。

不會寄垃圾信,隨時可取消。

“The researchers use Wasm's multi-memory feature to perform a one-time, fully automated memory reorganization of existing modules.”

翻譯一下就是:真正的風險不是 WebAssembly 自己壞掉,而是 C / C++ 那套老毛病,包成 Wasm 模組後還是會跟著進瀏覽器。原本程式如果有 buffer overflow,沒有隔離的話,它還是有機會去寫壞旁邊的資料。Wasm 不會因為你把它丟進瀏覽器,就自動把記憶體錯誤洗乾淨。

Bento 把 Wasm 記憶體切成隔間

文章把這點講得很清楚:像 Photoshop、Zoom、Twitch、Google Earth 這類軟體可以跑進瀏覽器,是因為 Wasm 把 native code 編成瀏覽器看得懂的格式。但如果原始碼在編譯前就不安全,Wasm 並不會神奇地幫你補上缺口。我以前也聽過一句很常見的話:「都進瀏覽器了,應該安全很多吧?」沒有,瀏覽器只是運送工具,bug 還是照樣上車。

實操上,如果你在 ship 的是從 memory-unsafe code 編出來的 Wasm,別再把瀏覽器當成安全解答。你要把 binary 本身當成可疑物件,然後在編譯後再加一層隔離。如果你能掌握原始碼,當然也該一起修;但如果你拿的是第三方模組,或是供應商不配合,那你就需要一種「事後也能做」的防線。

  • 先假設編譯後的 Wasm 仍可能帶著 buffer overflow 與 out-of-bounds write。
  • 把「跑在 WebAssembly」和「記憶體安全」分開看,這兩件事不是同義詞。
  • 優先找能對 binary 動手的防禦,不要只押 source tree。

Multi-memory 不是花招,它是這招能成立的底座

“They use Wasm's multi-memory feature to perform a one-time, fully automated memory reorganization of existing modules.”

也就是說,模組不再把記憶體當成一整塊共享大平面,而是切成一格一格的 compartment。這件事很重要,因為很多 exploitation 都是靠「旁邊剛好有東西」吃飯。只要攻擊者能從一個區域 overflow 到另一個區域,他就有機會改控制資料、HTML 內容,或其他敏感狀態。

我喜歡這種做法,因為它沒有在那邊硬發明一套全新的安全宇宙。它是直接用 WebAssembly 標準裡已經存在的 multi-memory 能力,去改模組的資料擺法。這讓整件事少掉很多唬爛味。安全提升不是來自玄學,而是來自把不同類型的資料拆開,不讓它們像一團亂線纏在一起。

TechXplore 用日本便當箱來比喻,我難得覺得這個比喻有用。你不會想把飯、菜、主菜全倒成一鍋。這裡也是一樣:如果 HTML 片段、buffer、控制資料都住在不同隔間,某一區 overflow 的時候,就比較不會把整個模組一起拖下水。

實操上,你如果在做 Wasm 工具,先做資料分級,再做 layout。重點不是「記憶體越多越好」,而是「高風險資料不要和可被攻擊者影響的 buffer 貼在一起」。這個順序不能反。

  • 把敏感狀態和外部輸入 buffer 分開。
  • 用 compartmentalization 限制單一 overflow 能碰到的範圍。
  • 盡量用自動化規則重排,不要靠人工手工擺位。

它比常見的安全表演好,是因為部署現實比較不會騙人

“Existing approaches to securing Wasm modules are hardly practical.”

這句話我很同意,因為很多安全方案技術上很漂亮,實際上卻很難上線。有些要 source code,但你常常拿不到,尤其是商用 off-the-shelf 軟體。有些要特殊硬體。有些要客製 browser。當你要部署團隊同時改 browser、改硬體、改 pipeline,基本上就是在叫大家不要發佈了。

Bento 把 Wasm 記憶體切成隔間

翻譯一下就是:最好用的安全控制,是你真的能部署的那個。這篇研究瞄準的是 COTS applications,這個方向是對的。真實世界的 browser app 不是乾淨的研究 demo,它們是 vendor binary、外來 library、還有一堆沒人想碰的 build chain 疊起來的怪物。

我以前也被那種「secure by design」方案坑過,表面上很美,背後其實默默假設所有人都會重寫所有東西。那不是方案,那是祈禱。這篇的 pitch 比較務實:拿編譯好的 module,做自動化記憶體重整,其它都先別動。

實操上,如果你是平台方或 browser-adjacent runtime 的維護者,先問自己一件事:你的 mitigation 是不是很依賴開發者配合?如果答案是 yes,落地就會很痛。反過來,如果你在做這類工具,binary-only 支援、零 app changes,應該是預設要求,不是加分題。

拿 Heartbleed 來驗,才知道這不是玩具

“The researchers tested the effectiveness of the bento approach using known security vulnerabilities, including the infamous Heartbleed bug.”

翻譯一下就是:他們沒有只拿一個玩具 overflow 來自我感動。Heartbleed 這名字一出來,大家就知道這不是紙上談兵。它是那種會讓人立刻有感的 memory disclosure bug,因為它真的醜、真的廣、也真的讓人記很久。如果一個 layout defense 能擋住這一類問題,那它就不只是漂亮而已。

文章還說,研究團隊展示了這個方法可以防住真實世界、而且是廣泛使用的應用程式攻擊。這點我在意。不是看它有多優雅,而是看它能不能扛住大家熟悉的失誤模式。安全研究最怕的就是只在自己設計的假場景裡贏得很漂亮,一到現實就散掉。

我以前看過 sandboxing 的工作也一樣:如果 demo 只能打掉合成 payload,沒人會真的信;但如果它能處理大家已經知道怎麼利用的 bug class,事情就不一樣了。標準很簡單:它能不能阻止老掉牙的記憶體錯誤,真的變成 browser-side compromise?

實操上,你在評估 Wasm 安全工具時,不要只看 crash test。你要問它有沒有對 memory disclosure bug 做驗證。能擋洩漏,才比較像真的有防線。

沒有明顯 slowdown,才有機會真的被採用

“They will notice neither longer loading times nor a significantly larger memory footprint.”

翻譯一下就是:安全故事只講一半沒用,成本才是另一半。只要 mitigation 讓 app 變慢、變重、變卡,產品團隊就會在心裡把它劃掉。使用者不會因為你說這個防線很優雅就接受更長的開啟時間和更高的記憶體占用。

這一點我特別在意。很多 security research 花了全部力氣證明攻擊被擋住,然後對成本輕輕帶過。但在 browser 軟體裡,成本就是全部。你藏不住 latency,也藏不住 memory bloat。只要使用者感覺得到,這個功能就已經有麻煩了。

文章說研究者沒有看到明顯的載入時間或記憶體 footprint 增加。我把它當成強但仍然是研究階段的主張,不會直接當成通用保證。不過它很重要,因為它先回答了產品團隊最常問的那句話:「這會壞掉什麼?」如果答案是「看起來不太會」,採用門檻就低很多。

實操上,你如果要做 hardening,從第一天就測 startup time、resident memory、steady-state overhead。不要等到最後才補 performance 測試。只要安全提升換來可見 slowdown,你就得換設計。

這其實是 binary hardening 的 playbook,不只是 WebAssembly 小技巧

“One-time, fully automated memory reorganization of existing modules.”

翻譯一下就是:這篇真正值得抄的,不是「WebAssembly 可以做一個很酷的事」,而是「編譯後的軟體可以在沒有 source changes 的情況下,被後處理成更安全的樣子」。這才是我覺得該被注意的地方。

這種思路其實不只適用 WebAssembly。只要你有第三方 binary、又沒辦法重建,這招就有機會派上用場。Wasm 只是目前最適合拿來驗證的場景,因為 browser 會把 memory boundary 變得很明顯,也很殘酷。但更大的 pattern 是:檢查 binary、分類 memory、把危險區域切開,然後盡量少動 runtime。

我偏愛那種尊重部署現實的工具。只要一個防禦方案只能在完美的 greenfield stack 內運作,我腦中就會先把它歸類成「有趣,但先放著」。如果它能包住既有軟體,而且不把維運變成科學專案,那才是真的有機會被用。

實操上,你評估 hardening 技術時,直接問三個問題:能不能不用 source?能不能不用特殊硬體?能不能不用改 browser 或使用者流程?只要其中一題答案是否,落地摩擦通常就不小。

可抄的模板

# Bento-style WebAssembly hardening checklist(可直接改成你們內部規範)

## 目標
把 WebAssembly binary 裡高風險的記憶體區域拆開,讓單一 buffer overflow 不會順手寫壞不相干的資料。

## 適用情境
- 你有 C / C++ 編譯成 Wasm 的模組
- 你不完全信任模組的記憶體安全
- 你需要的是 binary-level 防禦,不是重寫原始碼
- 你不想碰 custom browser 或特殊硬體

## 核心做法
1. 解析編譯後的 Wasm module。
2. 依資料風險與用途分類 memory regions。
3. 重新組織模組,改用多個 memories 或 compartments。
4. 把 attacker-influenced buffers 跟 sensitive state 分開。
5. 驗證新 layout 不會帶來明顯 runtime cost。

## 分區規則
- 外部輸入 buffer 獨立放一區。
- HTML、script-like content、control data 分開。
- 不要把敏感 pointers 跟容易 overflow 的 arrays 擺一起。
- 優先用自動化分組,不要手工微調到最後變成維護地獄。

## 安全檢查
- 用已知 memory disclosure bugs 測一次。
- 用 buffer overflow payload 測一次。
- 驗證一個 compartment 的 corruption 不會碰到另一個 compartment。
- 重測 startup time 與 memory footprint。

## 部署問題清單
- 能不能直接吃 existing binaries?
- 需不需要 source code?
- 需不需要改 browser?
- 需不需要特殊硬體?
- overhead 低不低到能真的 ship?

## 內部政策範本
我們只接受能在編譯後自動隔離高風險記憶體區域的 Wasm hardening。若模組無法安全 compartmentalize,就先不要上線,直到 layout 被修正。

這版是我會直接丟給團隊看的版本,不是論文摘要。它不會幫你把 Bento 實作出來,但它把操作原則講清楚了:把 memory 切開、部署面保持乾淨、測試要對準真實 exploit class。

來源致謝:我主要根據 TechXplore 的原文 https://techxplore.com/news/2026-06-webassembly-memory-layout-heartbleed-style.html,以及 ACM 論文 Bento: Fine-Grained Memory Isolation for COTS WebAssembly Binaries 做整理。文中的白話拆解、判讀方式與模板是我的衍生整理。