CVE-2005-4720 Firefox 1.0.6 segfaults on this malformed .html page

RESOLVED FIXED

Status

()

Core
Layout
--
critical
RESOLVED FIXED
13 years ago
13 years ago

People

(Reporter: Tom Ferris, Unassigned)

Tracking

({crash, verified1.8})

1.7 Branch
x86
Linux
crash, verified1.8
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(4 attachments)

(Reporter)

Description

13 years ago
User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6

When browsing to a malformed .html page, Firefox will segfault.

Reproducible: Always

Steps to Reproduce:
1.Browse to malformed page.
2.
3.

Actual Results:  
program sefaults, creating a core file.

Expected Results:  
parsed the page properly.

not sure.
"malformed .html page" is pretty general.  There are millions of them on the Web
that we don't segfault on.  Could you attach an example of the HTML that we do
segfault on?  (See "Create a New Attachment" above.)
(Reporter)

Comment 2

13 years ago
Sorry, I thought I had attached it.  Will the file be kept private?  Also, since
this is a security bug will I be eligable for the bug bounty program?
(Reporter)

Comment 3

13 years ago
Created attachment 191611 [details]
firefox-death.html

The following attached file will cause firefox 1.0.6 on linux to sefault.  This
file must be placed on a webserver in order to reproduce the crash.
(Reporter)

Comment 4

13 years ago
It appears that this flaw is in fact exploitable.  I was finally able to get a
debug version of firefox working.
Component: General → Layout
Product: Firefox → Core
QA Contact: general → layout
Version: unspecified → Trunk
Version: Trunk → 1.7 Branch
Can someone host that attachment on a public web server in a way that allows
anyone to run under a debugger and see what's going wrong?

Confirming based on Tom's testimony and some correspondence with dveditz, which
started with Tom's mail to security@mozilla.org last week (Dan is at OSCON this
week, not sure where that correspondence left off).  We need to diagnose this
and make some decisions, pronto.

/be
Status: UNCONFIRMED → NEW
Ever confirmed: true
(In reply to comment #2)
> Sorry, I thought I had attached it.  Will the file be kept private?  Also, since
> this is a security bug will I be eligable for the bug bounty program?

Yes, and  yes.  We can use brute force to remove the attachment before making
the bug world-readable.

Dan Veditz remains your point of contact for this bug and any bounty issues, but
while he's out of town I think we need others to help here.  Did you run under a
debugger and get a stack backtrace?  If so, please attach it.

/be
(Reporter)

Comment 7

13 years ago
I have put the .html file up here:

https://hak.us/firefox-death.html

_PLEASE KEEP IT PRIVATE_

I have not disclosed this flaw to anyone else.  Also, I am having problems
getting  firefox src to compile on my mandrake box.  Once I get it working, Ill
post the stack backtrace.
Created attachment 191625 [details]
stdout/err log

My debug build of the AVIARY_1_0_1_20050124_BRANCH corresponding to 1.0.6 does
not crash on that URL.	Attached here is the stdout/err from my run.  The
result in the browser is:

Not Found
The requested URL /0 was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an
ErrorDocument to handle the request. 

/be
(Reporter)

Comment 9

13 years ago
Here is what I get when I run it:

Core was generated by `./firefox-bin'.
Program terminated with signal 11, Segmentation fault.
#0  0x409b447c in ?? ()

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6

I am running the binary downloaded from the site.

-- Tom

Comment 10

13 years ago
No crash for me either.

Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.10) Gecko/20050716
Firefox/1.0.6

Updated

13 years ago
Keywords: crash
Summary: Firefox 1.0.6 will segfault when browsing a malformed .html page → Firefox 1.0.6 segfaults on this malformed .html page, seems exploitable
(Reporter)

Comment 11

13 years ago
(In reply to comment #10)
> No crash for me either.
> 
> Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.10) Gecko/20050716
> Firefox/1.0.6

Did you try hitting it from the webserver?  It doesnt seem to work when just
doing a File --> Open.  Also, I noticed your running on Mac OS X.  I have not
tried it on Mac OS X.

-- Tom

Updated

13 years ago
Blocks: 264944

Comment 12

13 years ago
tom: i don't suppose you could try:

./firefox -d -g `which valgrind`
run

(you'd need to install valgrind)
(Reporter)

Comment 13

13 years ago
(In reply to comment #12)
> tom: i don't suppose you could try:
> 
> ./firefox -d -g `which valgrind`
> run
> 
> (you'd need to install valgrind)

When doing this, firefox tries to launch the valgrind file?

Comment 14

13 years ago
./run-mozilla.sh -d -g `which valgrind` ./firefox-bin

Comment 15

13 years ago
i probably have -g and -d backwards, sorry. i've been using other os's lately...
(Reporter)

Comment 16

13 years ago
(In reply to comment #15)
> i probably have -g and -d backwards, sorry. i've been using other os's lately...

[tommy@mandrake firefox-installer]$ ./run-mozilla.sh -d -g `which valgrind`
./firefox-bin
valgrind: Missing --tool option
Available tools:
        addrcheck
        cachegrind
        corecheck
        helgrind
        lackey
        massif
        memcheck
        none
valgrind: Use --help for more information.

?  

Any other updates on this issue?

Comment 17

13 years ago
*sigh*

./run-mozilla.sh -g -d `which sh`

then use valgrind --help to figure out how to properly pick the right tool i 
believe the one we want is memcheck

so probably from the shell:
valgrind --tool=memcheck ./firefox-bin
(Reporter)

Comment 18

13 years ago
(In reply to comment #17)
> *sigh*
> 
> ./run-mozilla.sh -g -d `which sh`
> 
> then use valgrind --help to figure out how to properly pick the right tool i 
> believe the one we want is memcheck
> 
> so probably from the shell:
> valgrind --tool=memcheck ./firefox-bin

/me runs...

No such luck... Is anyone else looking/working on this?  Doesnt really seem to
be a very big deal.  

Comment 19

13 years ago
sorry, nothing bad happens for me on windows (i'm running under purify). and i
don't have resources allocated to test under linux from work.
I've had no luck getting this to crash. Did you ever get a crash with a
stacktrace? Does our official release crash? If so you could make sure Talkback
is installed and just give us a talkback number.

If you simplify the testcase does it still crash for you? Is it just one of the
junk attributes that causes the problem, or do you need a combination to confuse
Firefox. A stack trace or talkback report would quite probably point us at the
problem attribute.

In mail to security@mozilla.org you mention a crash on a windows version that
looked like a null dereference. That was the most common result of the various
mangler-style crashes we've seen, though there were one or two that were
different and potentially exploitable. Is the linux crash also a null dereference?
(Reporter)

Comment 21

13 years ago
(In reply to comment #20)
> I've had no luck getting this to crash. Did you ever get a crash with a
> stacktrace? Does our official release crash? If so you could make sure Talkback
> is installed and just give us a talkback number.
> 
> If you simplify the testcase does it still crash for you? Is it just one of the
> junk attributes that causes the problem, or do you need a combination to confuse
> Firefox. A stack trace or talkback report would quite probably point us at the
> problem attribute.
> 
> In mail to security@mozilla.org you mention a crash on a windows version that
> looked like a null dereference. That was the most common result of the various
> mangler-style crashes we've seen, though there were one or two that were
> different and potentially exploitable. Is the linux crash also a null dereference?


No, this Linux issue seems to be a format string.  I am not 100% sure though.  I
find it amazing that _noone_ can get this to crash??~!~!?  I am just running
1.0.6 linux version from the download site.  Talkback is installed, but does not
popup after the crash because the browser just dies.
Attachment 191611 [details] doesn't crash for me on Linux branch.

Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.10) Gecko/20050715
Firefox/1.0.6 SUSE/1.0.6-4.1
Works for me as well on Linux build from AVIARY_1_0_1_20050124_BRANCH (plus my
patch for bug 307259).  No valgrind warnings other than the usual ones.
Er, sorry, that was a trunk build.  But I don't see a crash or valgrind warnings
with an aviary 1.0.1 branch build either.

Comment 25

13 years ago
I'm able to reproduce crash here on Mandriva cooker, with mozilla.org 1.0.6
tarball (and also with our own package).

it is crashing gdk, with both gtk2.8 or gtk2.6 (well, it is not really gtk
fault, window witdh is set to 33364810 :) :

stack with gtk 2.8 :
#0  0xb7a8c2d7 in IA__gdk_window_object_get_type () at gdkwindow.c:199
#1  0xb7aa97c8 in gdk_window_compute_parent_pos (window=0x8f0c910,
    parent_pos=0xbf6570a0) at gdkgeometry-x11.c:828
#2  0xb7aa8e88 in _gdk_window_move_resize_child (window=0x94945f8, x=0, y=0,
    width=33364810, height=150) at gdkgeometry-x11.c:613
#3  0xb7ab84fe in IA__gdk_window_resize (window=0x94945f8, width=33364810,
    height=150) at gdkwindow-x11.c:1740
#4  0x08216184 in nsReadingIterator<unsigned short>::advance ()
#5  0x08210f29 in nsReadingIterator<unsigned short>::advance ()
#6  0x0821495e in nsReadingIterator<unsigned short>::advance ()
#7  0x0839734e in nsPRUint32Key::Clone ()
#8  0x08399ac0 in nsPRUint32Key::Clone ()
#9  0x0839c044 in nsPRUint32Key::Clone ()
#10 0x0839681a in nsPRUint32Key::Clone ()
#11 0x082147a5 in nsReadingIterator<unsigned short>::advance ()
#12 0x08214737 in nsReadingIterator<unsigned short>::advance ()

crash with gtk 2.6 :
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1220467008 (LWP 4426)]
0xb75bbbff in free () from /lib/tls/libc.so.6
(gdb) bt
#0  0xb75bbbff in free () from /lib/tls/libc.so.6
#1  0xb75bd6ef in malloc () from /lib/tls/libc.so.6
#2  0xb79f29d6 in IA__g_malloc (n_bytes=3077056640) at gmem.c:137
#3  0xb7b13676 in IA__gdk_region_rectangle (rectangle=0x933098c)
    at gdkregion-generic.c:146
#4  0xb7b2eca0 in gdk_window_clip_changed (window=0x944e428,
    old_clip=0x933098c, new_clip=0xbf388134) at gdkgeometry-x11.c:1080
#5  0xb7b2dc2d in _gdk_window_move_resize_child (window=0x944e428, x=0, y=0,
    width=33364830, height=150) at gdkgeometry-x11.c:505
#6  0xb7b3a288 in IA__gdk_window_resize (window=0x944e428, width=33364830,
    height=150) at gdkwindow-x11.c:1739
#7  0x08216184 in nsReadingIterator<unsigned short>::advance ()
#8  0x08210f29 in nsReadingIterator<unsigned short>::advance ()
#9  0x0821495e in nsReadingIterator<unsigned short>::advance ()
#10 0x0839734e in nsPRUint32Key::Clone ()
#11 0x08399ac0 in nsPRUint32Key::Clone ()
#12 0x0839c044 in nsPRUint32Key::Clone ()


OK, so I managed to reproduce this with a 1.0.6 Firefox opt Linux build.  I
can't reproduce with a debug build or even an opt -g build...  In the build in
which I did reproduce, I get an infinite recursion stack overflow with the
following basic unit:

#3357 0xb7ab4990 in nsWidget::DispatchEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk.so
#3358 0xb7ab486d in nsWidget::DispatchWindowEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk.so
#3359 0xb7ab39b4 in nsWidget::OnResize ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk.so
#3360 0xb7abbaf4 in nsWindow::Resize ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk.so
#3361 0xb6d020a9 in nsView::SetDimensions ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#3362 0xb6d04eaa in nsViewManager::SetWindowDimensions ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#3363 0xb6d07c0f in nsViewManager::DispatchEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#3364 0xb6d012be in HandleEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#3365 0xb7ab4990 in nsWidget::DispatchEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk.so
Though I just realized that might have been a GTK1 build... Let me do some more
testing.
OK, with a GTK2 build I get basically the same thing:

#29 0xb7ad32ec in nsCommonWidget::DispatchEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk2.so
#30 0xb7ad32b1 in nsCommonWidget::DispatchResizeEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk2.so
#31 0xb7ad3532 in nsCommonWidget::Resize ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk2.so
#32 0xb6d48361 in nsView::SetDimensions ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#33 0xb6d4b162 in nsViewManager::SetWindowDimensions ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#34 0xb6d4dec7 in nsViewManager::DispatchEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#35 0xb6d47576 in HandleEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libgklayout.so
#36 0xb7ad32ec in nsCommonWidget::DispatchEvent ()
   from /home/bzbarsky/mozilla/1.0.6/obj-opt/dist/bin/components/libwidget_gtk2.so
OK, so I've managed to reproduce in a "-Os -g" build.  Apparently just building
completely without -Osomething makes the bug not happen...  I see the same sort
of infinite recursion:

(gdb) frame 11
#11 0xb6dad556 in nsViewManager::SetWindowDimensions (this=0x82f8f60,
aWidth=466924892, 
    aHeight=2100) at ../../../mozilla/view/src/nsViewManager.h:361
361           mRootView->SetDimensions(newDim);
(gdb) frame 18
#18 0xb6dad556 in nsViewManager::SetWindowDimensions (this=0x82f8f60,
aWidth=466924878, 
    aHeight=2100) at ../../../mozilla/view/src/nsViewManager.h:361
361           mRootView->SetDimensions(newDim);
So here's the problem, I think.  The stack has:

(gdb) frame 19
#19 0xb6d4c162 in nsViewManager::SetWindowDimensions (this=0x0, aWidth=466901708, 
    aHeight=2100) at ../../../mozilla/view/src/nsViewManager.h:361
361           mRootView->SetDimensions(newDim);
(gdb) frame 17
#17 0xb7ad4532 in nsCommonWidget::Resize (this=0xb533ea18, aWidth=33350123,
aHeight=150, 
    aRepaint=1) at ../../../../mozilla/widget/src/gtk2/nsCommonWidget.cpp:319
319             DispatchResizeEvent(rect, status);

My p2t is 14.  Note that 14 * 33350123 == 466901722 (not 466901708).  So when
the widget resizes and notifies the viewmanager, we end up back in
nsView::SetDimensions with a new width, 14 twips bigger.  Repeat ad infinitum.

Now I did some tests, and 466901708 is quite definitely an integral multiple of
14, and the quotient is 33350122 (not 33350123).

I'm not sure _why_ the optimizer is screwing us over here (again, without -O
there is no crash).  I tried writing a simple program that duplicates what we do
here, which is (once you inline stuff):

  PRInt32((float(466901708) * 0.0714285746f) + 0.5f)

but that gives me the right results even compiled with optimization enabled...
One two other things:

1) If all the crashes involved are stack overflow (and that's the only kind I've
been able to reproduce), is this exploitable?

2) On trunk we explicitly don't resize the widget right then, so this issue
can't arise.
The other possibility to consider, of course, is that we had an overflow that
clobbered the stack...
We really need to at least sort out what's going on here for sure.
Flags: blocking1.7.13?
Flags: blocking-aviary1.0.8?
(Reporter)

Comment 34

13 years ago
Created attachment 197653 [details]
simplified test case

a more simplified test case.
Yeah.  So in this case the iframe has width 33333333 and the t2p is 14 and we have:

(gdb) p 33333333 * (float)(1/14.0) * (float)14
$44 = 33333334.490116104

And so forth.  Note that casting is actually very important here.  That is:

(gdb) p (float)(33333333) * (float)(1/14.0) * (float)14
$47 = 33333333.49011606

because 

(gdb) p (float)(33333333)
$48 = 33333332

Also note:

(gdb) p 1/14.0
$49 = 0.071428571428571425
(gdb) p (float)(1/14.0)
$51 = 0.0714285746

So the basic problems are:

1)  1/14 cannot be represented very well in a float; the error is on the order
of 3 parts in 10^6.
2)  33333333 cannot be represented in a float either; it becomes 33333333 when cast.
Created attachment 197769 [details]
C++ file that shows the problem

When I compile this with 'g++ test.cpp' I get:

33350124
0
33350122
Real test: 33333334.000000

If I compile with 'g++ -O test.cpp' I get:

33350122
0
33350122
Real test: 33333334.000000

If I cast aTwips to double instead of float in NSTwipsToIntPixels, I get the
33350124 result no matter what.  So this seems like an inlining issue of some
sort.

If I multiply by float(1/14.0) first (before multiplying by float(14.0)) I get
33333336.000000.
So summary:  This is a stack overflow.  I don't know whether those are
exploitable in general or not; dveditz, jruderman would have to comment on that.

There's no clear way to fix this given our use of equality testing here; even
switching to floats all over wouldn't help.  :(
(Reporter)

Comment 38

13 years ago
Stack overflows are every researchers dream. ;-]  Of course they are exploitable..
(In reply to comment #38)
> Stack overflows are every researchers dream. ;-]  Of course they are
> exploitable..

You are confusing stack buffer overflows, which may be used to overwrite return
addresses and direct control flow to code written by the attacker, with a stack
overflow, which causes the OS to kill the entire process -- at which point no
exploit is possible.

/be

Right. This is not a buffer overflow.  This is a "there are 700,000 function
calls on the stack and the kernel kills the process the next time a function
call is attempted" overflow.
Opening bug (which I actually meant to ask about doing a few days ago, but it
dropped off my list of things to do).
Group: security
As others have said, this is not an exploitable bug.  A stack overflow can
either cause the system to get slow due to disk IO or to kill the process
(depends on memory, VM, and how much the OS will allow a stack to grow before
killing the process).  The only systems where stack overflows are exploitable
are ones without memory protection.  This can occur in some small devices like a
network processor or router with no MMU; that's not the case here.
Summary: Firefox 1.0.6 segfaults on this malformed .html page, seems exploitable → Firefox 1.0.6 segfaults on this malformed .html page

Comment 44

13 years ago
no crash for me on a firefox 1.5 beta 2 candidate build on windows.

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b5) Gecko/20051004
Firefox/1.4.1

Can someone check a recent Mac build?

Are others still seeing this on Linux?
On trunk this was almost certainly fixed by widget change caching.
No problem on Mac 1.5beta2

Comment 47

13 years ago
No problem on Linux 1.5beta2

Comment 48

13 years ago
I guess we should close this one out and mark fixed-1.5b2

Comment 49

13 years ago
>Additional Comment #45 From Boris Zbarsky  2005-10-06 19:59 PDT  
>
>On trunk this was almost certainly fixed by widget change caching.

this widget caching bug? -> https://bugzilla.mozilla.org/show_bug.cgi?id=238493

Comment 51

13 years ago
marking fixed
Status: NEW → RESOLVED
Last Resolved: 13 years ago
Resolution: --- → FIXED

Updated

13 years ago
Keywords: fixed1.8
Which direction of duping ought we to have with bug 292279 which also reported
<iframe width="33333333">, back in April?
*** Bug 292279 has been marked as a duplicate of this bug. ***

Comment 54

13 years ago
no crash in either testcase firefox 1.5 rc2 winxp/linux
Keywords: fixed1.8 → verified1.8
bz: should this really block 1.0.8? It's non-exploitable, fixed in recent builds, and the widget caching patch (bug 238493) might be a little more risk than we want in 1.0.x

Comment 56

13 years ago
> Which direction of duping ought we to have with bug 292279 which also reported
> <iframe width="33333333">, back in April?

Well I think it is clear I saw it first!  So if there's a bounty I'd claim it ;)

Otherwise it doesn't really matter too much.

Steve
--
(Reporter)

Comment 57

13 years ago
(In reply to comment #56)
> > Which direction of duping ought we to have with bug 292279 which also reported
> > <iframe width="33333333">, back in April?
> 
> Well I think it is clear I saw it first!  So if there's a bounty I'd claim it
> ;)

Its all you buddy.. ;) hehe

> 
> Otherwise it doesn't really matter too much.
> 
> Steve
> --
> 

Is there anything else I can help with?

-- Tom
> bz: should this really block 1.0.8?

Nope.  I set that nomination flag back when we still didn't know what was going on here.  We definitely do not want widget caching on the 1.7 branch.
Flags: blocking1.7.13?
Flags: blocking-aviary1.0.8?

Updated

13 years ago
Summary: Firefox 1.0.6 segfaults on this malformed .html page → CVE-2005-4720 Firefox 1.0.6 segfaults on this malformed .html page
You need to log in before you can comment on or make changes to this bug.