Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Flerov/97c5f0a58ce42e439d982ad019ded4e9 to your computer and use it in GitHub Desktop.

Select an option

Save Flerov/97c5f0a58ce42e439d982ad019ded4e9 to your computer and use it in GitHub Desktop.

Revisions

  1. @saelo saelo created this gist Oct 27, 2019.
    107 changes: 107 additions & 0 deletions 3_years_of_attacking_javascript_engines.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    |=-----------------------------------------------------------------------=|
    |=-------------=[ 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