Closed Bug 1017095 (ZDI-CAN-2360) Opened 7 years ago Closed 7 years ago

Mozilla Firefox Javascript JIT Use-After-Free Remote Code Execution Vulnerability

Categories

(Core :: JavaScript Engine: JIT, defect)

29 Branch
defect
Not set
normal

Tracking

()

RESOLVED INVALID
Tracking Status
firefox29 --- ?
firefox30 --- ?
firefox31 --- ?
firefox32 --- ?
firefox33 --- ?
firefox-esr24 --- ?

People

(Reporter: curtisk, Assigned: jandem)

Details

(Keywords: csectype-uaf, sec-critical, Whiteboard: [reporter-external][PoC is windows only?])

Attachments

(2 files)

ZDI-CAN-2360: Mozilla Firefox Javascript JIT Use-After-Free Remote Code Execution Vulnerability


-- CVSS -----------------------------------------

6.8, AV:N/AC:M/Au:N/C:P/I:P/A:P


-- ABSTRACT -------------------------------------

HP's Zero Day Initiative has identified a vulnerability affecting the following products:

  Mozilla Firefox


-- VULNERABILITY DETAILS ------------------------

Tested against Firefox 29.0.1 as well as the nightly build from May 20th

Although pdfjs is used to trigger this vulnerability (by having an iframe with a src set to a PDF), pdfjs is not required for this vulnerability.  The issue lies in setting the iframe to 'about:blank' which results in freeing the JIT'd section.  After the event handler returns, execution continues in the now-freed section.  Note that this is a handle exception, which means it can be triggered over and over again until control is achieved.

From the latest stable:

```
(6fc.488): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0e32c401 ebx=0e32c1fc ecx=088d2d4c edx=ffffff87 esi=00000000 edi=088d2d40
eip=34ad328e esp=0e32c1d8 ebp=0000003a iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010216
34ad328e ??              ???
0:044> kv
ChildEBP RetAddr  Args to Child              
WARNING: Frame IP not in any known module. Following frames may be wrong.
0e32c1d4 088d2d40 00000002 0e32c1fc 0e32c1e8 0x34ad328e
0e32c220 689a444d 0e32c248 34ad25ca 17b71930 0x88d2d40
0e32c240 1cfe6c90 197529e0 00000009 00000075 mozjs!js::jit::DoUseCountFallback+0x18d (FPO: [4,3,0]) (CONV: cdecl) [c:\builds\moz2_slave\rel-m-rel-w32_bld-000000000000\build\js\src\jit\baselineic.cpp @ 941]
0e32c254 19f00150 1a2fa610 1a2fa5b0 1a2f4b50 0x1cfe6c90
0e32c258 1a2fa610 1a2fa5b0 1a2f4b50 1965dc68 0x19f00150
0e32c25c 1a2fa5b0 1a2f4b50 1965dc68 000000b8 0x1a2fa610
0e32c260 1a2f4b50 1965dc68 000000b8 0000003a 0x1a2fa5b0
0e32c264 1965dc68 000000b8 0000003a 00000000 0x1a2f4b50
0e32c268 00000000 0000003a 00000000 1a2f4c40 0x1965dc68
0:044> !lmi mozjs
Loaded Module Info: [mozjs] 
         Module: mozjs
   Base Address: 68870000
     Image Name: C:\Program Files\Mozilla Firefox\mozjs.dll
   Machine Type: 332 (I386)
     Time Stamp: 53697ed1 Tue May 06 19:31:13 2014
           Size: 3b2000
       CheckSum: 3b522f
Characteristics: 2122  
Debug Data Dirs: Type  Size     VA  Pointer
             CODEVIEW    76, 353328,  352328 RSDS - GUID: {C423AAFA-2595-4167-AD8E-42AF2A254F35}
               Age: 2, Pdb: c:\builds\moz2_slave\rel-m-rel-w32_bld-000000000000\build\obj-firefox\js\src\js\src\mozjs.pdb
     Image Type: FILE     - Image read successfully from debugger.
                 C:\Program Files\Mozilla Firefox\mozjs.dll
    Symbol Type: PDB      - Symbols loaded successfully from symbol server.
                 z:\export\symbols\mozjs.pdb\C423AAFA25954167AD8E42AF2A254F352\mozjs.pdb
       Compiler: C++ - front end [16.0 bld 30319] - back end [16.0 bld 30319]
    Load Report: private symbols & lines, not source indexed 
                 z:\export\symbols\mozjs.pdb\C423AAFA25954167AD8E42AF2A254F352\mozjs.pdb
0:044> lmvm mozjs
start    end        module name
68870000 68c22000   mozjs      (private pdb symbols)  z:\export\symbols\mozjs.pdb\C423AAFA25954167AD8E42AF2A254F352\mozjs.pdb
    Loaded symbol image file: C:\Program Files\Mozilla Firefox\mozjs.dll
    Image path: C:\Program Files\Mozilla Firefox\mozjs.dll
    Image name: mozjs.dll
    Timestamp:        Tue May 06 19:31:13 2014 (53697ED1)
    CheckSum:         003B522F
    ImageSize:        003B2000
    Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4
0:044> !heap -p -a @eip

0:044> !exchain
0e32f6dc: xul!XPT_DoHeader+5be8 (669ebc99)
0e32f774: MSVCR100!__newclmap+80f96 (6abfb582)
0e32f7cc: ntdll!_except_handler4+0 (7763e115)
  CRT scope  0, filter: ntdll!__RtlUserThreadStart+2e (77697f33)
                func:   ntdll!__RtlUserThreadStart+63 (776982a8)
Invalid exception stack at ffffffff



From the nightly:

(58c.f64): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=11fbbb01 ebx=11fbb9ac ecx=0142ed0c edx=ffffff87 esi=00000000 edi=0142ed00
eip=25ca1229 esp=11fbb988 ebp=13f3a760 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010212
25ca1229 ??              ???
0:045> kv
ChildEBP RetAddr  Args to Child              
WARNING: Frame IP not in any known module. Following frames may be wrong.
11fbb984 0142ed00 00000002 11fbb9ac 11fbb998 0x25ca1229
11fbb988 00000000 11fbb9ac 11fbb998 00000000 0x142ed00
0:045> !lmi mozjs
Loaded Module Info: [mozjs] 
         Module: mozjs
   Base Address: 67af0000
     Image Name: C:\Program Files\Nightly\mozjs.dll
   Machine Type: 332 (I386)
     Time Stamp: 537c8f0d Wed May 21 06:33:33 2014
           Size: 3cc000
       CheckSum: 3d1fdb
Characteristics: 2122  
Debug Data Dirs: Type  Size     VA  Pointer
             CODEVIEW    6f, 36c9c0,  36bbc0 RSDS - GUID: {7355EEF5-E99E-4100-B3C9-75FD4B9A7DDB}
               Age: 2, Pdb: c:\builds\moz2_slave\m-cen-w32-ntly-000000000000000\build\obj-firefox\js\src\mozjs.pdb
    Symbol Type: DEFERRED - No error - symbol load deferred
    Load Report: no symbols loaded
0:045> lmvm mozjs
start    end        module name
67af0000 67ebc000   mozjs      (deferred)             
    Image path: C:\Program Files\Nightly\mozjs.dll
    Image name: mozjs.dll
    Timestamp:        Wed May 21 06:33:33 2014 (537C8F0D)
    CheckSum:         003D1FDB
    ImageSize:        003CC000
    Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4
0:045> !exchain
11fbfbcc: xul!_except_handler4+0 (635ed3e9)
  CRT scope  0, filter: xul!MessageLoop::RunHandler+30 (6305f90f)
                func:   xul!MessageLoop::RunHandler+3c (6305f91b)
11fbfc64: MSVCR100!_except_handler4+0 (6ae3b582)
  CRT scope  0, filter: MSVCR100!_callthreadstartex+21 (6ae0c6e4)
                func:   MSVCR100!_callthreadstartex+35 (6ae0c6f8)
11fbfcbc: ntdll!_except_handler4+0 (7763e115)
  CRT scope  0, filter: ntdll!__RtlUserThreadStart+2e (77697f33)
                func:   ntdll!__RtlUserThreadStart+63 (776982a8)
Invalid exception stack at ffffffff

-- CREDIT ---------------------------------------

This vulnerability was discovered by:

   SkyLined working with HP's Zero Day Initiative

-- FURTHER DETAILS ------------------------------

If supporting files were contained with this report they are provided within a password protected ZIP file. The password is the ZDI candidate number in the form: ZDI-CAN-XXXX where XXXX is the ID number.

Please confirm receipt of this report. We expect all vendors to remediate ZDI vulnerabilities within 120 days of the reported date. If you are ready to release a patch at any point leading up the the deadline please coordinate with us so that we may release our advisory detailing the issue. If the 120 day deadline is reached and no patch has been made available we will release a limited public advisory with our own mitigations so that the public can protect themselves in the absence of a patch. Please keep us updated regarding the status of this issue and feel free to contact us at any time:

Zero Day Initiative
zdi-disclosures@tippingpoint.com

The PGP key used for all ZDI vendor communications is available from:

     http://www.zerodayinitiative.com/documents/zdi-pgp-key.asc

-- INFORMATION ABOUT THE ZDI ---------------------

Established by TippingPoint and acquired by Hewlett-Packard, The Zero Day Initiative (ZDI) represents a best-of-breed model for rewarding security researchers for responsibly disclosing discovered vulnerabilities.

The ZDI is unique in how the acquired vulnerability information is used. The ZDI does not re-sell the vulnerability details or any exploit code. Instead, upon notifying the affected product vendor, the ZDI provides its HP TippingPoint customers with zero day protection through its intrusion prevention technology. Explicit details regarding the specifics of the vulnerability are not exposed to any parties until an official vendor patch is publicly available.

    http://www.zerodayinitiative.com

-- DISCLOSURE POLICY ----------------------------

Our vulnerability disclosure policy is available online at:

    http://www.zerodayinitiative.com/advisories/disclosure_policy/
Version: unspecified → 29 Branch
Keywords: sec-critical
Whiteboard: [reporter-external]
Unfortunately I can't repro this. On Mac I do get a crash with a null JSContext with the latest nightlies, but it seems unrelated.

On Windows 7 it doesn't crash with Nightly and 29.0.1... Is anybody able to reproduce this?
Curtis, is there more info in the mail? For instance, index.html has an alert() and it shows a dialog. Should I close it immediately? Leave it open for a while?

We can't fix this if we can't reproduce it; the summary is too vague for that.
Flags: needinfo?(curtisk)
NI from some other people on the JS team with Windows.

Please download the two attachments, open index.html and see if it crashes; shouldn't take long.
Flags: needinfo?(kvijayan)
Flags: needinfo?(jwalden+bmo)
And if it does crash, please try a debug build (available on tbpl) as well.
Pretty much insta-crash on my homebrew Win64 trunk build after clicking OK:

mozjs.dll!JS_BeginRequest(JSContext * cx) Line 730	C++
xul.dll!mozilla::ThreadsafeAutoJSContext::ThreadsafeAutoJSContext() Line 218	C++
xul.dll!mozilla::dom::Promise::MaybeReportRejected() Line 1039	C++
xul.dll!mozilla::dom::Promise::~Promise() Line 422	C++
xul.dll!mozilla::dom::Promise::DeleteCycleCollectable() Line 399	C++
xul.dll!SnowWhiteKiller::~SnowWhiteKiller() Line 2605	C++
xul.dll!nsCycleCollector::FreeSnowWhite(bool aUntilNoSWInPurpleBuffer) Line 2778	C++
xul.dll!nsCycleCollector::BeginCollection(ccType aCCType, nsICycleCollectorListener * aManualListener) Line 3707	C++
xul.dll!nsCycleCollector::Collect(ccType aCCType, js::SliceBudget & aBudget, nsICycleCollectorListener * aManualListener) Line 3576	C++
xul.dll!nsCycleCollector_collect(nsICycleCollectorListener * aManualListener) Line 4128	C++
mozjs.dll!js::gc::GCRuntime::collect(bool incremental, __int64 budget, js::JSGCInvocationKind gckind, JS::gcreason::Reason reason) Line 4874	C++
mozjs.dll!js::DestroyContext(JSContext * cx, js::DestroyContextMode mode) Line 263	C++
xul.dll!`anonymous namespace'::WorkerThreadPrimaryRunnable::Run() Line 2584	C++
xul.dll!nsThread::ProcessNextEvent(bool mayWait, bool * result) Line 720	C++
xul.dll!NS_ProcessNextEvent(nsIThread * thread, bool mayWait) Line 263	C++
xul.dll!mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate * aDelegate) Line 307	C++
xul.dll!MessageLoop::Run() Line 197	C++
xul.dll!nsThread::ThreadFunc(void * arg) Line 316	C++
nss3.dll!_PR_NativeRunThread(void * arg) Line 419	C
nss3.dll!pr_root(void * arg) Line 91	C
msvcr110.dll!_callthreadstartex() Line 354	C
msvcr110.dll!_threadstartex(void * ptd) Line 332	C

Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:32.0) Gecko/20100101 Firefox/32.0
Built from https://hg.mozilla.org/mozilla-central/rev/cbe4f69c2e9c
I can repro this with latest nightly on my Win8 laptop.  Actually just loading the PDF directly in the browser causes the crash - don't even need the index.html
Flags: needinfo?(kvijayan)
I think the JS_BeginRequest crash is unrelated... It looks different from the crashes in comment 0 and I don't get it on 29. Does 29 also crash?

Needinfo from bent and khuey on the stack in comment 7.
Flags: needinfo?(khuey)
Flags: needinfo?(bent.mozilla)
The worker/~Promise thing looks a lot like bug 967005 (JS_DestroyContext => CC => ~Promise => MaybeReportRejected => JS_BeginRequest with NULL JSContext). Is it possible bug 967005 didn't fix this completely?
Flags: needinfo?(nsm.nikhil)
Flags: needinfo?(khuey)
Flags: needinfo?(bent.mozilla)
I downloaded Aurora, Beta, and Release tip Windows dep builds and can't reproduce the crash with any of them. I used a fresh profile to be safe. The same new profile still reproduces with trunk, though.

Using today's trunk nightly:
https://crash-stats.mozilla.com/report/index/4ae71d28-219f-4bee-9b09-b3bad2140528
I can't reproduce this using a latest nightly on Linux 64. Debug build. Is JITing enabled in debug builds?

Bug 967005 should have fixed the issue unless this code is creating Promises in the close handler. That is the only possible situation I can think of.
(In reply to Nikhil Marathe [:nsm] (needinfo? please) from comment #12)
> I can't reproduce this using a latest nightly on Linux 64. Debug build. Is
> JITing enabled in debug builds?

Try a 32-bit opt build and maybe also on Windows/Mac; that's where we saw this. JITs are enabled in debug builds, but I'm pretty sure this is unrelated.

(In reply to Nikhil Marathe [:nsm] (needinfo? please) from comment #12)
> Bug 967005 should have fixed the issue unless this code is creating Promises
> in the close handler. That is the only possible situation I can think of.

We're seeing this with the latest Nightlies, so it's definitely not fixed.
Flags: needinfo?(nsm.nikhil)
Nikhil: if you still can't reproduce it we can give you more information, just let us know what would be useful for you.
Sorry, but there's nothing I can do here; we can't repro the crash. We *can* repro another crash with latest nightlies, but it seems unrelated: (a) very different signature (b) doesn't crash on older branches (c) crashes when opening the pdf directly, while the exploit is in the html file.

We need at least the following information from the reporter:

(1) Are you still able to reproduce this with 29.0.1, with a clean profile?
(2) After opening index.html, should we close the alert() dialog immediately? Should we leave it open?
(3) How long does it take for the website to crash?
(4) Which Windows version do you use? (We tried Windows 7 and 8.)
Flags: needinfo?(curtisk)
Whiteboard: [reporter-external] → [reporter-external][windows only ?]
I've made requests to ZDI for more information and we're waiting.
Flags: needinfo?(zdi)
Flags: needinfo?(zdi-disclosures)
since this came from skylined in the first place I added him to the bug and maybe he will respond to a need info and help us repro this
Flags: needinfo?(berendjanwever)
Flags: needinfo?(berendjanwever)
Flags: needinfo?(berendjanwever)
Flags: needinfo?(skylined)
Have you tried running in a VM and restricting the amount of memory? For example, the VUPEN pwn2own bug only reliably reproduced when you had 2Gb memory because it was tuned for the contest targets. Our own dev machines might have too much memory, try a machine with 2 or 4Gb.
Whiteboard: [reporter-external][windows only ?] → [reporter-external]
Whiteboard: [reporter-external] → [reporter-external][PoC is windows only?]
Flags: needinfo?(zdi)
Response from ZDI
-----//-----
Hello,

Regarding ZDI-CAN-2360, our vetting reseacher replied that: 

"A debugger needs to be attached in order to see the access violation. The exception handler catches it and prevents the process from crashing, but this could still be used for malicious purposes."

Does this help?

Thank you again,
Shannon
Flags: needinfo?(zdi-disclosures)
> "A debugger needs to be attached in order to see the access violation. The
> exception handler catches it and prevents the process from crashing, but
> this could still be used for malicious purposes."

I've been told to ignore first chance exceptions on Windows whenever I found fuzzing testcases. Should I still ignore them moving forward?
Curtis, thanks for forwarding that message, very useful.

The exception handler we install for interrupting JIT code is probably the one catching this. The question is whether the segfault is benign/expected (one we triggered to interrupt JIT code) or a real UAF. I'll try to find out.
I'll investigate more, but after catching this in a debugger it really looks like this is the normal JIT code interrupt mechanism.

Whenever we want to interrupt Ion/asm.js JIT code, we protect the code pages so that executing or accessing it on the main thread will trigger a segfault. Our signal handler then catches this, makes the memory accessible again and patches some instructions so that the main thread will call into C++ to handle the interrupt when it continues.
You can test that proposition (which sounds likely) by setting the env var JS_DISABLE_SLOW_SCRIPT_SIGNALS.
(In reply to Jan de Mooij [:jandem] from comment #22)
> I'll investigate more, but after catching this in a debugger it really looks
> like this is the normal JIT code interrupt mechanism.
> 
> Whenever we want to interrupt Ion/asm.js JIT code, we protect the code pages
> so that executing or accessing it on the main thread will trigger a
> segfault. Our signal handler then catches this, makes the memory accessible
> again and patches some instructions so that the main thread will call into
> C++ to handle the interrupt when it continues.

Sorry for the stupid question, so is this still a valid bug?
Flags: needinfo?(nsm.nikhil)
It might be useful to pass back information about debugging the engine when jit-ting is enabled.

In gdb I set:

handle SIGSEGV nostop noprint pass

to allow segfaults to pass through to the engine.  Segfaults caused as part of routine execution will not get trapped by gdb, but unhandled segfaults will still interrupt the debugger.
(In reply to Nikhil Marathe [:nsm] (needinfo? please) from comment #24)
> Sorry for the stupid question, so is this still a valid bug?

The "crash" described in comment 0 looks like it is not a real bug... But comment 7 is definitely a real crash. If we close this bug we should make sure we don't forget to investigate that.
I can still repro this on Windows, but not if I set JS_DISABLE_SLOW_SCRIPT_SIGNALS=1. This confirms what I wrote in comment 22; this is not a (security) bug but expected behavior.

SkyLined, please let me know if I'm missing something.
Status: UNCONFIRMED → RESOLVED
Closed: 7 years ago
Flags: needinfo?(jwalden+bmo)
Resolution: --- → INVALID
(In reply to ben turner [:bent] (use the needinfo? flag!) from comment #26)
> The "crash" described in comment 0 looks like it is not a real bug... But
> comment 7 is definitely a real crash. If we close this bug we should make
> sure we don't forget to investigate that.

Agreed, I'll file a new bug for that.
(In reply to Jan de Mooij [:jandem] from comment #28)
> Agreed, I'll file a new bug for that.

Bug 1020226.
ZDI disagrees with our assessment of this as non-exploitable so I am reopening the bug. They will be sending additional details.
Status: RESOLVED → REOPENED
Ever confirmed: true
Resolution: INVALID → ---
@Jan de Mooij: Sorry for the slow reply; I was on holiday. I did not investigate the issue thoroughly before handing it over to the ZDI, so I defer to their judgement.
Flags: needinfo?(berendjanwever)
Response from ZDI to sec@

In short: We disagree that there is no vulnerability here.  Although the exceptions are handled, because of the way they are triggered one could reclaim the memory of the callee before execution returns to it. Basically, although the exception may be innocuous in the general case, in this case it is not.
Jan: is this issue actionable? Do we still believe this exception is not exploitable?

(I assigned this bug to you because you have investigated and reproduced this crash. We should probably have an assignee contact for every sec bug that is being investigated. If you're not the right contact, please feel free to unassign or reassign. :)
Assignee: nobody → jdemooij
Flags: needinfo?(jdemooij)
> In short: We disagree that there is no vulnerability here.  Although the
> exceptions are handled, because of the way they are triggered one could
> reclaim the memory of the callee before execution returns to it. Basically,
> although the exception may be innocuous in the general case, in this case it
> is not.

FF is purposefully causing the exception by changing the protection bits on memory (while keeping it allocated).  This memory is not freed, so it cannot be reclaimed.
Flags: needinfo?(skylined)
(In reply to Chris Peterson (:cpeterson) from comment #33)
> Jan: is this issue actionable? Do we still believe this exception is not
> exploitable?

The issue reported here is not a (security) bug but by design, so there's nothing we can/should do. See also comment 34.
Flags: needinfo?(jdemooij)
ZDI is contacting the researcher about this, per email.
update from ZDI recieved to mozsec
-----//-----
Hello Daniel,

Thank you for waiting.  After talking to our vetting researcher again,
and to the finder, Skylined, we do agree.  The case can be closed. 
Thank you again.

Shannon
Status: REOPENED → RESOLVED
Closed: 7 years ago7 years ago
Resolution: --- → INVALID
Group: core-security, javascript-core-security
You need to log in before you can comment on or make changes to this bug.