flawopen.com/安全事件/ANGLE 通用底层 0-day:一次漏洞攻陷 Chrome、iOS 与 Android

ANGLE 通用底层 0-day:一次漏洞攻陷 Chrome、iOS 与 Android

严重危险 · CVSS 8.8 CWE-125 / CWE-787: 堆内存越界访问 跨平台漏洞复盘 · 2025年12月
ELI5 (通俗解释)

想象两家激烈竞争的智能手机巨头(苹果与谷歌)。为了节省软件研发成本,两家公司不约而同地在手机内部安装了完全相同的第三方电源适配器(ANGLE 图形层),专门用来把国际通用电压(WebGL 标准)转换为各自手机电池接受的本地电压(iPhone 的 Metal 与 Android 的 Vulkan)。黑客通过网页发送了一种极其刁钻的特制电脉冲,导致这个共享适配器瞬间过热起火烧穿保险丝,黑客便能用完全相同的网页攻击代码,同时攻陷苹果 iPhone 与安卓手机。

核心技术概念
ANGLE (底层图形抽象引擎)
由 Google 主导开源的跨平台图形兼容层,将 WebGL/OpenGL 指令实时转换为硬件原生 API(如 Apple Metal、Windows Direct3D、Android Vulkan)。
跨生态软件供应链单一依赖
竞争对手操作系统由于底层采用了相同开源解析库,导致单一漏洞能够击穿多个平台防线的现象。
Metal 后端深度纹理内存切片
ANGLE 在 Apple 系统中负责将 WebGL 标准深度格式转换为 Metal 显存纹理格式的专门处理模块。
WebGL 内存越界漏洞利用
攻击者无需用户同意,仅凭普通网页上运行的 Canvas 3D JavaScript 脚本,即可操控底层 C++ 显存结构造成越界读写。

事件全景复盘

In December 2025, Google and Apple issued rare, synchronized emergency security advisories for a high-severity zero-day vulnerability tracked as CVE-2025-14174. The vulnerability was discovered by Google's Threat Analysis Group (TAG) and Apple's Security Engineering and Architecture (SEAR) team being actively exploited in targeted in-the-wild cyber espionage campaigns.

Unlike conventional browser zero-days that target V8 (Chrome) or JavaScriptCore (Safari), CVE-2025-14174 originated in ANGLE (Almost Native Graphics Layer Engine). Because Google maintains ANGLE for Chromium and Apple integrates ANGLE into WebKit for WebGL translation on iOS and iPadOS, this single memory corruption bug compromised both browser ecosystems simultaneously.

An attacker hosting a malicious web page could trigger an out-of-bounds memory write simply by rendering a WebGL canvas with specially crafted depth texture parameters, gaining arbitrary code execution within the browser's sandboxed renderer process on both Android/Chrome and iOS/Safari.

技术根本原因深度剖析

1. Arithmetic Overflow in Depth Texture Slice Calculation

When uploading 3D or 2D depth textures via WebGL (texImage2D / texSubImage2D), ANGLE's Metal backend calculated the required staging buffer size based on width, height, and depth. Due to improper bounds validation during pixel format conversion (from WebGL depth formats like DEPTH_COMPONENT32F to Metal's MTLPixelFormatDepth32Float), the row pitch calculation under-allocated memory while the copy routine processed the full input buffer, writing past the heap boundary.

2. Shared Library Dependency Across Competing Vendors

Apple adopted Google's ANGLE to accelerate WebGL compliance without maintaining a separate translation layer from scratch. This created a shared software monoculture: an exploit payload weaponized against ANGLE on Chrome was instantly portable to Apple's WebKit WebContent process on iOS and iPadOS.

3. WebGL Direct Surface Exposure to Untrusted Web Pages

WebGL exposes direct GPU memory management primitives (buffers, textures, shaders) to arbitrary JavaScript execution. Because WebGL is enabled by default across all mobile browsers and requires zero user prompts, any visited web link can immediately interact with complex C++ graphics drivers.

漏洞机制 vs 生产加固对比

VULNERABLE: UNVALIDATED TEXTURE BUFFER ALLOCATION (ANGLE)
// Conceptual flaw in ANGLE's Metal backend (TextureMtl.mm)
angle::Result TextureMtl::uploadDepthData(const gl::Context *context,
                                         const gl::Extents &size,
                                         const uint8_t *clientData) {
  // Bug: Row pitch multiplication lacks overflow checks
  size_t rowPitch = size.width * getBytesPerPixel(mFormat);
  size_t allocationSize = rowPitch * size.height; // Can overflow!

  // Under-allocated heap buffer
  uint8_t *stagingBuffer = new uint8_t[allocationSize];

  // HEAP OUT-OF-BOUNDS WRITE:
  // Metal copy helper copies bytes calculated from internal format stride!
  CopyDepthSlices(clientData, stagingBuffer, size.width, size.height, size.depth);
  return angle::Result::Continue;
}
HARDENED: CHECKED ARITHMETIC & BOUNDS CLAMPING
// Fixed ANGLE implementation using base::CheckedNumeric
angle::Result TextureMtl::uploadDepthData(const gl::Context *context,
                                         const gl::Extents &size,
                                         const uint8_t *clientData) {
  // Fix 1: Safe integer multiplication preventing integer overflow
  base::CheckedNumeric<size_t> safeSize = size.width;
  safeSize *= getBytesPerPixel(mFormat);
  safeSize *= size.height;
  safeSize *= size.depth;

  if (!safeSize.IsValid()) {
    return angle::Result::Stop; // Reject invalid buffer geometry
  }

  size_t allocationSize = safeSize.ValueOrDie();
  std::vector<uint8_t> stagingBuffer(allocationSize);

  // Fix 2: Bounded copy strictly constrained to allocated buffer capacity
  SafeCopyDepthSlices(clientData, stagingBuffer.data(), stagingBuffer.size(), size);
  return angle::Result::Continue;
}

检测策略与安全控制措施

# Network IDS / Zeek: Flag suspicious WebGL depth texture exploit payloads event http_reply(c: connection, msg: http_message) { if (msg$body matches /texImage2D.*DEPTH_COMPONENT/) ... } # Safari / Chrome Enterprise Policy: Disable WebGL for high-security endpoints defaults write com.apple.Safari WebKitPreferences.webGLEnabled -bool false # Chrome Enterprise Policy: Enforce software fallback or block WebGL on untrusted origins {"Disable3DAPIs": true, "WebGLBlockedForOrigins": ["*"]}
In high-threat environments (journalists, government officials, defense personnel), enforce Apple's Lockdown Mode or Chrome's Disable3DAPIs policy to completely eliminate the WebGL/ANGLE attack surface.

软件供应链启示与纵深防御清单

参考来源与官方公告