Created
October 27, 2019 16:04
-
-
Save saelo/dd598a91a27ddd7cb9e410dc92bf37a1 to your computer and use it in GitHub Desktop.
3 Years of Attacking JavaScript Engines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|=-----------------------------------------------------------------------=| | |
|=-------------=[ 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