世界を動かす技術を、日本語で。

スケールでのRust: WhatsAppのための追加のセキュリティ層

概要

  • WhatsAppが Rust製の新しいセキュリティレイヤー を導入
  • メディア一貫性ライブラリ をRustでグローバル展開
  • Stagefright脆弱性 を契機に独自防御策を強化
  • Kaleidoscope による多層的なファイル検査・防御
  • 今後も Rust採用拡大 とセキュリティ強化を推進

WhatsAppにおけるRust導入によるセキュリティ強化

  • WhatsAppは 30億人超 のユーザーに デフォルトでエンドツーエンド暗号化 を提供
  • サイバー脅威に対抗するため、 防御戦略の継続的な進化 を実施
  • ユーザーが 画像・動画・ドキュメント を共有する機能に潜むリスクへの対策
  • 一見無害なファイルに隠された 高度なマルウェア への警告と検出
  • OSやアプリの 未修正の脆弱性 を突く攻撃への対抗策

Stagefright脆弱性とメディアファイル保護の転機

  • 2015年、Androidの Stagefright脆弱性 が発覚
  • OS提供のメディアライブラリに依存していたためアプリ側でのパッチが困難
  • ユーザーのOSアップデートが遅れるリスクを回避する必要性
  • WhatsApp独自の wamedia(C++製) ライブラリを活用し、MP4標準外ファイルの検出機能を追加
  • OSアップデート不要で 迅速なユーザー保護 を実現

Rustによる大規模なメディア処理ライブラリ再構築

  • C++からRustへの並行開発 を選択し、互換性担保のため 差分ファジング・テスト を徹底
  • Rust標準ライブラリ導入による バイナリサイズ増加 や多様なプラットフォーム対応の課題
  • 16万行のC++コード9万行のRustコード に置き換え、パフォーマンス・メモリ効率も向上
  • Android、iOS、Mac、Web、ウェアラブルなど 多様なプラットフォームに展開
  • Rustによる メモリ安全性とセキュリティ向上 を実現

多層的なファイル検査システム「Kaleidoscope」

  • ファイル構造の 非準拠チェック で下流ライブラリの脆弱性悪用を防止
  • PDF内の埋め込みファイルやスクリプト の検出など、リスク指標で追加チェック
  • 拡張子やMIMEタイプ偽装 の検知
  • 実行ファイルなど危険度の高いファイル をUIで特別扱い
  • Kaleidoscopeにより 非公式クライアントや悪質な添付ファイル からユーザー保護

Rust導入による運用と今後の展望

  • 毎月、 数十億台の端末・ブラウザ にRust製ライブラリを配布
  • 世界最大規模の Rustコード展開事例
  • Rustは クライアントサイドの本番運用に耐えうる言語 であることを実証

WhatsAppのアプリセキュリティ全体戦略とRustの役割

  • エンドツーエンド暗号化やバックアップ暗号化キー透明性技術 など多層的なセキュリティ
  • CVE報告 やバグバウンティ、外部監査、ファジング、静的解析など多角的なリスク特定
  • C/C++由来のメモリ安全性問題 が高リスクの主因であることを分析
  • 攻撃対象領域の最小化、C/C++コードのセキュリティ保証、 新規コードはメモリ安全言語(Rust等)を標準採用
  • CFI、メモリアロケータ強化、安全API など追加防御策
  • C/C++開発者への 専門セキュリティトレーニング や自動解析、厳格な修正SLA

Rust採用拡大と今後のセキュリティ強化

  • Rustにより 高性能・高安全なクロスプラットフォームライブラリ を構築
  • 防御層のさらなる強化と 裏側でのユーザー保護 を推進
  • WhatsAppおよびMetaのセキュリティチームが Rust導入の機会を積極的に推進
  • 今後も Rust採用の加速 とセキュリティ強化に注力

Hackerたちの意見

すごいね!Signalも似たようなことやってるのかな?libsignalはRustで実装されてるけど、他の部分はどうなんだろう。

「私たちは、これはRustで書かれたライブラリの中で、世界的に見ても最大の展開だと信じています。」たぶんこれが真実だと思う。WhatsAppを使ってる電話の数は、Windows 11のPCよりも多いからね。WhatsAppがlibsignalを使ってることを考えると、彼らがRustライブラリを直接使ってないって考えてもいいのかな?

WhatsAppはlibsignalを使ってないし、AndroidはもうかなりRustが使われてるよ。WhatsAppよりも世界中に展開されてるし(スマホだけじゃなくて、カスタムAndroidで動いてる「組み込み」用途もたくさんある)。

「MicrosoftはRustに慣れてきている:成功と課題のレビュー」を見ると、全体の取り組みはAzure側に偏ってるみたいだね。GDI領域みたいな控えめな採用はあるけど、Windows側でのRustの採用はあまり進んでない。まだまだCとC++の対立が続いてる感じ。

こういうリライトの一番難しいところは、実際のRustの実装よりも、レガシーパーサーとのバグ互換性を維持することだね。現実のメディアファイルはほとんどが何らかの形で不正だから、C++のコードが暗黙的に処理してた部分がある。厳密なパーサーを書くと、正しいユーザーデータを壊しちゃうことになる。差分ファジングが、その挙動を手動で何百万ものエッジケースをレビューせずにマッピングする唯一の実用的な方法みたいだね。

この「wamedia」のデザイン目標は、メディアプレイヤーとのバグ互換性を_維持しない_ことみたいだね。

AIの返信?

かなり印象的だね。こんなに多くのバグがメモリアクセスに起因してるとは知らなかった。

公平に言うと、Rustのコードの信頼性がC++よりも高いのは、メモリエラー(境界外アクセス、解放後使用、型混乱など)だけが理由じゃないよ。他にもいろいろあるんだ。* 未定義動作がない(unsafeの外では、これはかなり避けやすい)。C++には、メモリエラーとは直接関係ない未定義動作の原因がたくさんある、例えば符号付き整数のオーバーフローや関数からのreturnを忘れることとか。* より強力な型システム。これら二つの要素は、信頼性にかなり大きな影響を与えるんだ。

「初期のバイナリサイズの増加は、Rust標準ライブラリを取り入れたことによるものでした。」彼らはこれについて何をしたか言ってないよね?ただ受け入れたのかな?

記事全体がちょっと薄っぺらい感じがするから、技術的なプレゼンテーションというよりPRとして読んだよ。

たぶんそうだね。バイナリごとに約300KBで、一度きりのコストだよ。標準ライブラリを無効にすれば完全に回避できるけど、それは不便だから、通常は組み込みデバイス向けに書くときだけだね。問題はサイズそのものじゃなくて、C++とRustが混在するコードベースでのRust依存関係の重複なんだ。ビルドシステムのサンドイッチ(C++ => Rust => C++ => Rustみたいなライブラリ依存関係があるとき)になっちゃうと、各Rust/Cargoビルドがlibstdやクレートのコピーをバンドルしちゃう。だから、リンカーがそれを整理できるようにするか、Cargoの代わりにBazelを使ってRustとC++の依存関係を一つの依存関係ツリーの一部として扱う必要があるんだ。

Hacker Newsで議論の続きを見る