3 Years of Attacking JavaScript Engines
| |=-----------------------------------------------------------------------=| | |
| |=-------------=[ 3 Years of Attacking JavaScript Engines ]=-------------=| | |
| |=-----------------------------------------------------------------------=| | |
| |=------------------------------=[ saelo ]=------------------------------=| | |
| |=-----------------------------------------------------------------------=| | |
| The following are some brief notes about the changes that have taken place | |
| since the release of the "Attacking JavaScript Engines" paper [1]. In | |
| general, no big conceptional changes have happened since. Mitigations have | |
| been added to break some of the presented techniques and, as expected, a | |
| number of changes to engine implementation details have happened. | |
| --[ 2 - The bug | |
| The bug hunting focus seems to have shifted away from the interpreter and | |
| runtime and more into the JIT compiler land. | |
| ----[ 2.2 - About JavaScript conversion rules | |
| Additional callbacks, such as Symbol.ToPrimtive [2] as an alternative to | |
| the valueOf and toString properties, have been added to the JavaScript | |
| language and implemented by the popular engines. | |
| ----[ 3.1 - Garbage collector basics | |
| In addition to the GC properties as described in the original paper, JSC's | |
| garbage collector is now also concurrent [3]. | |
| ----[ 3.3 - Copied space | |
| The CopiedSpace has been removed from JavaScriptCore [4]. | |
| --[ 4 - Building exploit primitives | |
| With regards to exploit primitives, only minor changes have taken place since | |
| the release of the original paper, and the "addrof" and "fakeobj" primitives | |
| are still alive and kicking. Alternatively, a somewhat more abstract | |
| "corruptobj" primitive can also often be used to corrupt some part of an | |
| existing object and that way gain for example memory R/W [5]. | |
| ----[ 4.1 - Prerequisites: Int64 | |
| The Int64 module will (hopefully) soon no longer be necessary due to | |
| BigInts [6] becoming widely available. | |
| --[ 6 - Exploitation | |
| A few mitigations have been put into place to break the exploit techniques | |
| described in the original paper and are briefly described next. | |
| ----[ 6.1 - Predicting structure IDs | |
| StructureID randomization has been implemented [7]. The idea here is to | |
| randomize the Structure IDs so that predicting them in the way described in | |
| the original paper is no longer possible. I haven't really seen any public, | |
| generic bypasses for this. In any case, the same bug can often be exploited | |
| to also leak a structure ID or corrupt an existing object, thus eliminating | |
| the need to know a structure ID in the first place [8]. | |
| ----[ 6.2 - Putting things together: faking a Float64Array | |
| A "Gigacage" has been added to WebKit [9] which is designed to stop the | |
| abuse of ArrayBuffers and other objects as described in the original paper | |
| [10, 11]. The common bypass seems to be faking/corrupting JSArrays and that | |
| way obtaining a (slightly limited) memory R/W [8]. Abusing ArrayBuffers to | |
| gain memory R/W is, however, still possible in other engines. | |
| ----[ 6.3 - Executing shellcode | |
| On iOS, various generations of JIT mitigations have been developed and | |
| deployed [8], the latest of which uses custom CPU features to protect the | |
| JIT region from an attacker with an arbitrary memory write primitive [12]. | |
| Further, on arm64e, PAC is now used to verify the integrity of the | |
| generated machine code right before writing it into the executable JIT | |
| region [13]. It remains to be seen what the new standard (public) post-R/W | |
| exploitation technique will be. | |
| --[ 7 - Abusing the renderer process | |
| Disabling the SOP by compromising the renderer process is still possible in | |
| WebKit but no longer in Chromium due to site isolation [14]. | |
| Happy hacking :) | |
| ~saelo | |
| --[ 8 - References | |
| [1] http://phrack.org/papers/attacking_javascript_engines.html | |
| [2] https://tc39.es/ecma262/#sec-symbol.toprimitive | |
| [3] https://webkit.org/blog/7122/introducing-riptide-webkits-retreating- wavefront-concurrent-garbage-collector/ | |
| [4] https://github.com/WebKit/webkit/commit/d1725cb590133728edf29fce5258c7320657e455 | |
| [5] http://phrack.org/papers/jit_exploitation.html | |
| [6] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt | |
| [7] https://github.com/WebKit/webkit/commit/f19aec9c6319a216f336aacd1f5cc75abba49cdf | |
| [8] http://iokit.racing/jsctales.pdf | |
| [9] https://github.com/WebKit/webkit/commit/d2bbe276796add2f96b13717d703f86a588409c5 | |
| [10] https://phakeobj.netlify.com/posts/gigacage/ | |
| [11] https://labs.f-secure.com/archive/some-brief-notes-on-webkit-heap-hardening/ | |
| [12] https://siguza.github.io/APRR/ | |
| [13] https://github.com/WebKit/webkit/commit/80c907f12e5099c640897fb5e313ff1bd0dacf92 | |
| [14] https://www.chromium.org/Home/chromium-security/site-isolation |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment