Closed Bug 355069 Opened 18 years ago Closed 14 years ago

Bantown discusses an arbitrary code execution in the JavaScript implementation on any OS

Categories

(Core :: General, defect)

1.8 Branch
defect
Not set
critical

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: bantownsnitch, Unassigned)

Details

Attachments

(5 files, 1 obsolete file)

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1a3) Gecko/20060526 BonEcho/2.0a3
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1a3) Gecko/20060526 BonEcho/2.0a3

At LULZCON (see encyclodpedia dramatica) Bantown members discussed a bug found relating how javascript is handled/executed in all tested versions of firefox. Bantown specifically plans not to release the exploit but plans to exploit it.

So all the information I have is that one can execute arbitrary code in firefox via javascript.


See the post and slides at:
http://hepkitten.livejournal.com/513183.html

Reproducible: Always
No reason having this security-sensitive if it's just a link to a public blog.
Group: security
Product: Firefox → Core
Version: unspecified → 1.8 Branch
The link to the PowerPoint presentation (which supposedly has slides of the exploit) is completely dead. Are there any backup links for this? If not, there's not really any useful information on this LiveJournal entry.
The powerpoint presentation was still up when I read it, and I have a copy.  (It's 1.7MB, so I can't attach it.)

But here's the text of the relevant 4 slides.
As far as I can tell, all the code snippet provided does (in my 1.8 branch debug build) is fill up lots of memory.  Presumably, there's more code not shown.

Anybody know if the slides in question claiming to report a stack overflow or a stack buffer overrun?
(In reply to comment #4)
> As far as I can tell, all the code snippet provided does (in my 1.8 branch
> debug build) is fill up lots of memory.  Presumably, there's more code not
> shown.
> 
> Anybody know if the slides in question claiming to report a stack overflow or a
> stack buffer overrun?

None of the code after
         for (var j = 0; j < 300; j++)
            hezbstr += hezbstr; 
can ever execute...
I did get a crash on my first run, with dbg set to false, no attached debugger, creating a new object and calling it's hello method, but that could just as easily be an ordinary crash bug. No crashes or exceptions on subsequent runs, with or without a debugger attached.
Summary: Bantown discusses a arbitrary code execution in the JavaScript implementation on any OS → Bantown discusses an arbitrary code execution in the JavaScript implementation on any OS
One possibility (pointed out by Window) is that the script fills up memory, and there's an OOM crash somewhere.  I don't think that's the case, because doubling a string over and over is more likely to result in a single failed huge allocation than exhausting virtual memory.  But we could test for that, either by limiting how much memory Firefox is allowed to use (with |ulimit|?), or by testing on a 32-bit machine with enough RAM to not swap.

Another possibility, which I think is more likely based on the descriptions given by the presenters, is that there is some kind of "re-entrancy" in the JavaScript engine.  We already know that the JavaScript engine violates run-to-completion in bug 355097 and bug 52209.

jst, do you think this could be a result of bug 52209?

I don't understand how that would be connected to a "clever recursion trick" that lets you "fill the stack", though.  There are ways around JavaScript's recursion limits (e.g. bug 347157), but in any sane OS, a stack overflow is a safe segfault.
Attached file transcript from the talk (obsolete) —
I transcribed this from the DVD of the presentation just now.
I hate bug 253564.
Attachment #240905 - Attachment is obsolete: true
(In reply to comment #5)
> None of the code after
>          for (var j = 0; j < 300; j++)
>             hezbstr += hezbstr; 
> can ever execute...

Indeed. The example is either incomplete or can be replaced by:

Object.prototype.hello = function () {

    var wackyaddrs = unescape("%u0800%u0000%u1000%u0000%u2000%u0000%u4000%u0000");

    setTimeout(function () { var o = new Object (); o.hello(); }, 50);
    var hezbstr = dbg ? "loldongsloldongs!" + wackyaddrs : wackyaddrs;

    for (;;)
        hezbstr += hezbstr;
};

Then if there is a bug, then it is either an integer overflow when growing the string or in the timer implementation on low memory. 
QA Contact: general → general
(In reply to comment #7)
> huge allocation than exhausting virtual memory.  But we could test for that,
> either by limiting how much memory Firefox is allowed to use (with |ulimit|?),

FWIW, I did that yesterday on Linux (ulimit -v 750000), and I ended up crashing after quite a few "Javascript error: out of memory" due to new throwing (bug 324005).
(In reply to comment #10)
> Then if there is a bug, then it is either an integer overflow when growing the
> string

All JS string concats funnel through js_ConcatStrings, and since string length is bounded to 2^30 - 1, the allocation or reallocation there should not be able to overflow.

> or in the timer implementation on low memory. 

This is something to focus on.

/be
(In reply to comment #7)
> Another possibility, which I think is more likely based on the descriptions
> given by the presenters, is that there is some kind of "re-entrancy" in the
> JavaScript engine.  We already know that the JavaScript engine violates
> run-to-completion in bug 355097 and bug 52209.

It's not the JS engine, of course, that can violate run to completion.  It is the DOM embedding code, or other code in Gecko.  In a single (main) thread, the run-to-completion model can be subverted by any native method implementation, e.g. for a modal dialog function (alert/confirm/prompt).

The transcript shows cargo-cult science knowledge of JS ("threads", etc.), but you're right to smell something wrong here.  When I created JS in Netscape 2, I intentionally implemented run to completion as the execution model.  This meant that timeouts would defer while a modal dialog was flying.  Netscape 2-4, IE all versions, Safar, and Opera all follow this rule.  Mozilla does not.  Example:

data:text/html,<script>var i=0;function f(d){d.getElementById('t').value = ++i;}</script><body onload="setInterval(f, 1000, document)"><button onclick="prompt('foo')">click me</button><input id="t" size="4"></body>

Click on the "click me" button and let the prompt stay up; watch the text field show the counter incrementing.

/be
(In reply to comment #13)
> This meant
> that timeouts would defer while a modal dialog was flying.  Netscape 2-4, IE
> all versions, Safari, and Opera all follow this rule.  Mozilla does not. 
> Example:
> 
> data:text/html,<script>var i=0;function f(d){d.getElementById('t').value =
> ++i;}</script><body onload="setInterval(f, 1000, document)"><button
> onclick="prompt('foo')">click me</button><input id="t" size="4"></body>
> 
> Click on the "click me" button and let the prompt stay up; watch the text field
> show the counter incrementing.

This is bug 279518 at least (mark dups if you can identify true duplicates).

/be
Here's the full testcase from Mischa (via e-mail to Window). He didn't make any attempt to clean out extraneous cruft that accrued during development, this is the full raw testcase.

(the original sourced "js/core.js" and "js/dom.js", not sure which version specifically but presumably the current six-apart ones. Since they're utility libraries it probably doesn't matter much.)
Attachment #241005 - Attachment description: original source → original source [hangs/crashes browser]
In addition to the "setTimeout during alert" issue (bug 52209 and bug 279518), this testcase might be taking advantage of bug 324149, "Moving into an alert dialog sends a mousemove event".
(In reply to comment #12)
> 
> All JS string concats funnel through js_ConcatStrings, and since string length
> is bounded to 2^30 - 1, the allocation or reallocation there should not be able
> to overflow.
> 

if you manage to reach this bound, i.e. String.length== 2^30 -1, byte size 2G off by few bytes, i suspect you are already in trouble. actually even 2^30 - 5 may do iirc. the best i could do was about *around* 2^30 - 2^20. so please give the largest js string you can construct in any away on a 32 bit os.

suggest trying this testcase in a release build, because there some things are noops.

(In reply to comment #20)
ooops, this comment was total sh*t, don't take it seriously.
Is this crash still reproducible in Firefox 3.5?  If it isn't, we should resolve it as RESOLVED WORKSFORME.
Since no-one replied to Tanner, the last comment linked to a post saying there actually was no vulnerability here, and the testcase doesn't appear to have any effect on the browser, I hope I won't get yelled at for closing this one :)
Status: UNCONFIRMED → RESOLVED
Closed: 14 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: