Uint8Array pwn them all!

This week I take a look at the research blog post by @vupen Advanced Exploitation of Mozilla Firefox Use-after-free CVE-2012-0469 . It is one year old vulnerability, but thanks to it, simple idea come into my mind…

Exploitation of this vulnerability presented at vupen’s blogs, was not easy, because it have into arsenal just controlled OR for certain location, and it uses nothing more – which is quite interesting ! Because of that, exploitation grows complexity, and the first step was logical expanding length of string object, for memory leak. As the next move was performed OR at one tag-object targeting its VTable, which ends to arbitrary code execution.

but … in generation of HTML5 and its new features, more easier and more general method could be used for this exploitation

In previous blog post i focused on some HTML5 features, and one of them was container with byte-level access : Uint8Array . Logical is that this container have also length, and when we are able to expand it, similiar effect to patched string-object is achieved – but keep in mind that Uint8Array is far more effective -> byte-level acces and more important direct access to data!

So it seems no problem here … but, when you start spraying Uint8Array in this way

you will encounter that nothing happen! Magic is that original length which should be patched to achieve overflow effect is stored not in object whith data-buffer, but in its container…

So one option is to start spraying Uint8Array which will efectively spray 2objects in 2different part of heap, which can be problem, because length member is in smaller object so it can be little dizzy to hit this one …

But direct acces for Uint8Array made aviable system like subarray, which brings special functionality :

The range specified by the begin and end values is clamped to the valid index range for the current array.

And when you take a closer look to this subarray object, you recognize way how it is achieved. Simply, in subbaray object is defined length of substring and pointer to original buffer.

So next try! patch this size

and what happens  today ?

… and thats it! … now it is totaly sufficient look and patch at just one place -> subarray.length! We know that size of subbaray object is pretty aligned 0x50b, so why not to heapspray it ? .. whith this heapspray, when you are able to patch subarray.length you win! exactly, when you are able to patch length to native ~0x0, then you full pwn app (whole address space of current app), you can patch everthing you want and easier then ever before

  • Code
  • Get position :
    • By allocating 2 following Uint8Arrays, you can use address of second one, which you are able to read now, to get position info
    subarraylengthpatched_poc_7addressofcurrentpositionexposed_8
  • Perform leak :
    • searching trouch all address space of aplication throws access exception (PAGE_NOACCESS), so leak-ing addresses of modules, should be done in other way
    • just find out connections between objects, and you can ‘jump’ by referencing to the buffer whithout access violation ;)
    vtableleak_9vtableleake_data_avtableleak_functions_b
  • Patch everything :
    • Direct access of Uint8Array -> direct to subarray => .js code rule over byte-level acces to available address space!

  • Epic! :
    • as I mentioned, walking whole address space trough buffer cause access violation…
    • what could happen, when you are able to locate & patch this code ? done …

Back to CVE :

  • arsenal :
    • use-after-free
    • OR value (1<<max(0x1F)) to certain location (read vupen blog-post for vuln. details!)
  • goals :
    • via OR expand our subarray
  • problems :
    • calculations
      problem1problem2
    • on attacker controled value, thx to freed-object, are performed two different magic calculations :
      • after first calculation, have to be at calculated address value { 0x10 , 0x11, 0x12 }
      • result of second calculation should point to subarray.length
    • subarray objects are placed on heap page up to limit page + 0xFC00 -> bytes at address 0xFC0C4 and above are by default zer0ed == no controled access to them
  • solution :
    • how to craft values :
    • first i need to be able to alter subarray.length, which is resides on <PAGE, PAGE+0xFC00>, and these objects are pretty aligned :)
    • it seems, this can be what I need!

      but a little drawback is present .. i need to have at adress 0x218ff00c value { 0x10, 0x11, 0x12 }, but bytes at these adress a unused at zeroed by default … BUT! …
    • due this vulnerability specs, you are able to perform 2OR operations so lets go craft second value, which will patch our 0x218ff00c byte to 0x10!
      0x17a44 0x10 0x218ff00c 0x218ff044 [ 0x218bd00c ] > 0x218bd220

      it sounds nice, but now i still need { 0x10, 0x11, 0x12 } at address 0x218bd00c, but when you look at |PAGE + x * 0x100C| you should view values 0x6, which is related to subarray object.. so what next ? … after few experiments, try to allocate with subbaray also substring :) 

    • Ok so subarays and substrings are at collected at the same ‘page’ of heap, and if you spray correctly at the bottom of the page (especially at 0x219000c0 too :) ) would be subarray!
  • PoC :
    • just quick PoC

      ba w4 0x218ff00c ".if poi(0x218ff00c) = 0x10 {} .else {gc}"
      exploitation1exploitation2exploitation3exploitation4exploitation5exploitation6
      exploitation7exploitation8exploitation9exploitationaexploitationb
    • as you can see all goes according to the plan, except last access violation

       

Conclusions : Typed arrays are very powerfull in view of developer but also in hand of the attacker. Direct access, byte-level access make it ideal support for attack, and made a day for hard exploitable vulnerabilities … maybe some checks of overlaping length’s should not be bad idea…

* for testing was used FF11, but similiar (difference in offsets) it work in new FF, GC ..

Leave a comment

0 Comments.

Leave a Reply


[ Ctrl + Enter ]


Go To Top
Follow

Get every new post delivered to your Inbox

Join other followers: