
CVE-2026-74945, divulgazione di heap non inizializzato tramite un web font appositamente predisposto (sec-high)
Questa directory contiene un pacchetto di riproduzione onesto per una divulgazione di memoria non inizializzata nella gestione dei font di Firefox. Un font @font-face appositamente costruito porta il flusso di output di OTS in una lacuna di heap non inizializzato, e contenuti ordinari rileggono i byte di quella lacuna tramite l'API canvas measureText. È pensato per essere eseguito contro una build vulnerabile di Firefox scaricata localmente con soli dati sintetici. Non tocca mai alcun sistema live o di terze parti.
Repository PoC corrispondente: https://github.com/defineid/Palimpsest
Writeup: writeup-font-cmap-leak.html in questo portfolio.
| Campo | Valore |
|---|---|
| CVE | CVE-2026-74945 |
| Componente | Core / Graphics: Text |
| Classe | Divulgazione di memoria non inizializzata (CWE-908 · CWE-200) |
| Gravità | sec-high (divulgazione di memoria raggiungibile dal web) |
| Corretto in | Firefox 154 · ESR 140.14 |
| Bug | bugzilla.mozilla.org/show_bug.cgi?id=2057808 |
| Interazione | Nessuna · solo caricamento della pagina |
Firefox sanifica i web font tramite OTS prima dell'uso. Tre difetti indipendenti si allineano in modo che un font appositamente costruito lasci una lacuna di heap non inizializzato all'interno dell'output sanificato e il contenuto possa rileggerla:
moz_xrealloc) che non riempie di zeri il nuovo spazio.cmap di formato 14 con un nonDefaultUVSOffset elevato fa sì che OTS sposti in avanti il proprio flusso di output quando riserializza il font sanificato. L'intervallo saltato tra i byte scritti e la destinazione del seek viene consegnato al chiamante con heap non inizializzato, e forget() dimensiona il buffer fino all'offset più alto raggiunto.cmap anziché alla sottotabella, quindi un segmento il cui idRangeOffset esce dalla fine dei dati di formato 4 supera comunque il controllo e legge nei byte non inizializzati della sottotabella adiacente.Il font appositamente costruito abbina una sottotabella di formato 4, il cui ultimo segmento (0xFFFF) usa un idRangeOffset dispari e in overflow, con una sottotabella di formato 14 che porta un nonDefaultUVSOffset elevato, più maxp.numGlyphs = 65535 e un avanzamento hmtx distinto per ogni id di glifo (avanzamento == id del glifo). Misurare U+FFFF risolve quindi in un id di glifo letto dalla lacuna non inizializzata, e la sua larghezza di avanzamento, leggibile da script, divulga circa due byte di heap per misurazione su una finestra di circa 64 KB.
Una normale pagina web serve il font appositamente costruito tramite @font-face e chiama ctx.measureText(""). Non è richiesto alcun clic, permesso, estensione o modifica delle preferenze. OTS viene eseguito in-process e non è tra le librerie sandboxate, quindi i byte divulgati sono heap del processo di contenuto che può contenere puntatori o segreti.
| File | Scopo |
|---|---|
make_font.py | Costruisce leak.otf e leak.woff, i font appositamente costruiti. |
trigger.html | Pagina minimale che carica il font tramite @font-face e rilegge l'avanzamento di U+FFFF tramite measureText. |
https://ftp.mozilla.org/pub/firefox/releases/140.9.0esr/.pip install fonttools brotli
python3 make_font.py # writes leak.otf and leak.woff in this directory
Poi apri trigger.html nella build vulnerabile, da un percorso file:// o da un
server statico locale sotto il tuo controllo, e fai clic su Measure.
.notdef) e l'advance è 0. Nessun gap viene divulgato, perché il flusso di output
viene azzerato e la lookup di formato 4 è limitata alla propria subtable.make_font.py è stato eseguito qui con fontTools
4.63.0 e ha prodotto leak.otf (393816 byte) e leak.woff (132372 byte).
Il font generato è stato ri-analizzato dai byte grezzi e ogni ingrediente costruito
è stato confermato: maxp.numGlyphs = 65535, hhea.numberOfHMetrics = 65535, un
advance hmtx distinto per ogni glyph id (advance == glyph id), due subtable cmap
(platform 3 encoding 1 formato 4, e platform 0 encoding 5 formato
14), l'ultimo segmento del formato 4 endCode = 0xFFFF con un dispari che sfora
idRangeOffset = 0x4001, e il nonDefaultUVSOffset = 0x8000 del formato 14.trigger.html tu stesso contro una build vulnerabile locale per osservare la fuga.
Questo pacchetto dimostra l'input costruito e il percorso di ri-lettura; non è un
exploit weaponizzato e non include alcuna primitiva controllata di esecuzione di codice.Questo prende di mira una build scaricata localmente con dati di font sintetici e auto-generati, per un writeup della CVE segnalata dall'autore stesso e già corretta. Non attacca alcun servizio live o di terze parti.