ρ


program analysis, reversing & exploit writing

More on ASM.JS Payloads and Exploitation

At OffensiveCon 2018 I presented my already a bit dated ASM.JS JIT-Spray research. You can find more information in previous blogposts.

Besides using arithmetic calculations and array elements, another interesting technique to spray payloads is to use float values. Using these values as payload bytes has the advantage that an attacker’s shellcode resides continuous in memory at run time, because the float values are next to each other located in a constant pool. As the payload bytes are not interrupted by disturbing opcodes emitted by the ASM.JS compiler, all eight bytes of a double float constant are usable as payload.

If you are into (over)hyping and naming vulnerabilities you can call it: ConstantDesaster

So finally, I release the remaining code including our shellcode2asmjs (sc2asmjs.py) tool and exploits for CVE-2016-2819 and CVE-2016-1960. An exploit for CVE-2016-9079 is already available for some time. Most likely, sc2asmjs.py won’t be maintained anymore, however, you can still generate ASM.JS JIT-Spray payloads of different kinds and insert your favorite assembly or binary Metasploit payload to exploit vulnerable Mozilla Firefox versions.

Some last words on CVE-2016-2819 and CVE-2016-1960: There is a very detailed public exploit for CVE-2016-1960, which uses a bruteforce approach (see explanation). However, after a bit of diving into the vulnerable code and patches for both bugs, it was possible to change the inital crashing testcase to reach an easier to exploit code path. The goal is to reach line 1102 where we get EIP control when node->release() is called in nsHtml5TreeBuilder::pop():

firefox-44.0.2/parser/html/nsHtml5TreeBuilder.cpp:602
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
602  void
603  nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, bool selfClosing)
604  {
....
1092     case NS_HTML5TREE_BUILDER_DD_OR_DT: {
1093       eltPos = currentPtr;
1094       for (; ; ) {
1095         nsHtml5StackNode* node = stack[eltPos];
1096         if (node->getGroup() == group) {
....
1101           while (currentPtr >= eltPos) {
1102             pop();
1103           }
1104           break;
....
1107         }
1108         eltPos--;
1109       }
....
1113       NS_HTML5_BREAK(starttagloop);
1114     }

The code is equivalent for firefox-46.0.1/parser/html/nsHtml5TreeBuilder.cpp. As group is a constant on line 1096, we only need one exploit attempt to reach line 1102. This can be achieved when changing the last element from style to dd (see modification). And, as we only need EIP control when using ASM.JS JIT-Spray, exploitation becomes even more comfortable and easier. For more information take a look at the OffensiveCon 2018 slides.

Enjoy! Let me know if you find any mistakes, feedback is welcome!


Best,
Rh0