flawopen.com/보안 사고/ANGLE 범용 제로데이: Chrome, iOS, Android 동시 침해
경쟁 관계인 두 스마트폰 제조사(구글과 애플)가 개발 비용을 아끼기 위해 동일한 규격 변환 어댑터(ANGLE)를 기기 내부에 설치했다고 상상해보세요. 해커가 웹사이트를 통해 변환기에 과부하를 주는 신호를 보내 장치를 태워버렸고, 결과적으로 단 하나의 공격 코드로 아이폰과 안드로이드폰을 동시에 해킹했습니다.
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.
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.
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.
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.
// 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;
}
// 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": ["*"]}
base::CheckedNumeric in Chromium or safe math in Rust) for all graphics buffer and texture pitch calculations.