Bugzilla@Mozilla – Bug 622015
JavaScript Atom Invalid Index Vulnerability -- iDefense [V-ikgwbx1hqs]
Last modified: 2011-03-29 19:29:00 PDT
Summon comment box
Created attachment 500274 [details] PoC iDefense VCP Submission V-ikgwbx1hqs 12/29/2010 Mozilla Firefox JavaScript Atom Invalid Index Vulnerability Description: Remote exploitation of a memory corruption vulnerability in Mozilla Organization's FireFox could allow an attacker to execute arbitrary code with the privileges of the current user. The vulnerability occurs in the JavaScript engine (SpiderMonkey) of Mozilla FireFox. When compiling javascript, the Mozilla engine produces bytecode that is later interpreted in a virtual machine. Strings and other literals (so called atoms) are stored in an atom map. Opcodes that use values from the atom map take a 16 bit immediate constant operand that is used as an index in the atom map array. When more than 64k atoms are used, special handling is required because a 16 bit value would not suffice to address the desired atom. Therefore, the engine frames the opcode with an "indexbaseX" and a "resetbase0" opcode that move the atoms pointer forward and backward respectively. When an exception is thrown in between the indexbase and resetbase opcodes, the atoms pointer does not get reset and the exception object of the catch block is read from an invalid memory address. This results in an exploitable memory corruption vulnerability. Analysis: Exploitation of this vulnerability results in the execution of arbitrary code with the privileges of the user viewing the web page. To exploit this vulnerability, a targeted user must load a malicious webpage created by an attacker. An attacker typically accomplishes this via social engineering or injecting content into compromised, trusted sites. After the user visits the malicious web page, no further user interaction is needed. In order to exploit this vulnerability, it is necessary control various structures at the location of the invalid reference. By performing a heap spray it is possible to populate memory with the needed structures and obtain reliable arbitrary code execution. Credit: Christian Holler
Word has it that Igor is the one to handle this. Let us know if this turns out to be wrong.
Not blocking this bug, but it seems like we should reevaluate the space/time benefits of all this indexbase complexity.
(In reply to comment #2) > Not blocking this bug, but it seems like we should reevaluate the space/time > benefits of all this indexbase complexity. I am going to try 3-byte indexes and see how this affects interpreter-only benchmarks.
Created attachment 500368 [details] [review] v1 Here is an untested work-in-progress.
Created attachment 500411 [details] [review] v2 Here is another WIP - it still fails few tests during make check.
The resulting patch for expanding the literal index to 3 bytes is too big to port it to branches. Apparently the macros to work with the bytecode do not abstract the literal index sufficiently to allow for a small and easy to test patch. So I will delegate that to the bug 622557 while focusing here on hopefully one-liner fix.
A simpler test case that builds a function source with over 64K literals: var src = "var a=["; for(var i = 0; i != 1e5; ++i) src += "'a"+i+"',"; src += "]; i = 'xyz';"; src += "try { x.y; return a; } catch(e) { return this[i]; }"; var x = { get y() { throw 0; }}; var xyz = 42; assertEq(Function(src)(), 42); It asserts/crashes in debug/optimized builds.
Created attachment 500865 [details] [review] two-liner fix The fix adds missing re-initialization of atoms.
Comment on attachment 500865 [details] [review] two-liner fix Need back-porting, should be easy. /be
http://hg.mozilla.org/tracemonkey/rev/61e3418e4223
The bug is definitely critical
http://hg.mozilla.org/mozilla-central/rev/61e3418e4223
Guys, can we get this on the branches?
Please note that the particular PoC attached here is a shell PoC only and won't run in browser (it might even fail in the shell, it was tested with Ubuntu and the shell from Firefox 3.6.11 release). Exploitation in the browser works the same as in shell but requires more complicated heap spraying to work reliable. I won't ever publish the working exploit for the browser.
Fyi, successful exploitation in the shell looks like this: Program received signal SIGSEGV, Segmentation fault. 0x08177853 in js_Interpret (cx=0x81ba9e0) at jsops.cpp:2208 2208 ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp); (gdb) print fun->u.n.native $1 = (JSNative) 0xdeadbeef (gdb)
Created attachment 504464 [details] [review] fix for 19[12] The patch is a trivial backport to 1.9.2, here is a plain diff between the trunk and it: 4,7c4,7 < @@ -6805,7 +6805,6 @@ END_CASE(JSOP_ARRAYPUSH) < // Handle exceptions as if they came from the imacro-calling pc. < regs.pc = regs.fp->imacropc(); < regs.fp->clearImacropc(); --- > @@ -3069,7 +3069,6 @@ js_Interpret(JSContext *cx) > // Handle other exceptions as if they came from the imacro-calling pc. > regs.pc = fp->imacpc; > fp->imacpc = NULL; 10d9 < #endif 12c11,12 < @@ -6834,6 +6833,9 @@ END_CASE(JSOP_ARRAYPUSH) --- > JS_ASSERT((size_t)((fp->imacpc ? fp->imacpc : regs.pc) - script->code) < script->length); > @@ -3092,6 +3091,9 @@ js_Interpret(JSContext *cx)
Comment on attachment 504464 [details] [review] fix for 19[12] The 192 patch applies as-is to 191.
Comment on attachment 504464 [details] [review] fix for 19[12] a=LegNeato for 1.9.2.14 and 1.9.1.17
http://hg.mozilla.org/releases/mozilla-1.9.2/rev/2e5604a977d0 http://hg.mozilla.org/releases/mozilla-1.9.1/rev/4e5edc8a6382
Verified crash in 1.9.1.16 with PoC and fix in Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.17pre) Gecko/20110121 Shiretoko/3.5.17pre ( .NET CLR 3.5.30729). Same with 1.9.2.13 and Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.14pre) Gecko/20110121 Namoroka/3.6.14pre ( .NET CLR 3.5.30729).
Created attachment 512152 [details] [review] Fix for 1.9.0 Would that be enough for 1.9.0 ? (It looks like so ; at least the testcase doesn't crash anymore)
Comment on attachment 512152 [details] [review] Fix for 1.9.0 Please use diff -U8 the next time you attach the patch for a review to get more context.