Pageviews

Monday, 5 February 2018

Integer Underflow to RCE in Firefox

Hi Internet,

A 750$ bug :P Lets get started.

Underflow:
If the integer value used is less than the minimum signed or unsigned int. This is called an underflow and will also trigger a segmentation fault.

Summary of this issue:
Before this change, if the metadata for a dbm-format certificate (or presumably key) database were corrupted, ugly_split could do an unchecked subtraction resulting in unsigned integer underflow, and would attempt to operate on something it thought was very big, resulting in (at least) an out-of-bounds.

How I started :
I was using nginx server with HTTPS which host's nothing, however adding a certificate exception every time crashes my FF in Linux, but does not crashes in windows. Then i taught of running FF in debug mode to see where the crash happens

GDB Log :
(gdb) bt
#0  0x00007fffcf4a4c56 in ?? () from /usr/lib/firefox/libnssdbm3.so
#1  0x00007fffcf4a7a60 in ?? () from /usr/lib/firefox/libnssdbm3.so
#2  0x00007fffcf4a63fe in ?? () from /usr/lib/firefox/libnssdbm3.so
#3  0x00007fffcf4a7d1f in ?? () from /usr/lib/firefox/libnssdbm3.so
#4  0x00007fffcf4a7e32 in ?? () from /usr/lib/firefox/libnssdbm3.so
#5  0x00007fffcf4a9046 in ?? () from /usr/lib/firefox/libnssdbm3.so
#6  0x00007fffcf4b599a in ?? () from /usr/lib/firefox/libnssdbm3.so
#7  0x00007fffcf4b602a in ?? () from /usr/lib/firefox/libnssdbm3.so
#8  0x00007fffcf4b87c6 in ?? () from /usr/lib/firefox/libnssdbm3.so
#9  0x00007fffcf4b8d94 in ?? () from /usr/lib/firefox/libnssdbm3.so
#10 0x00007fffcf4b8e40 in ?? () from /usr/lib/firefox/libnssdbm3.so
#11 0x00007fffcf4b08ee in ?? () from /usr/lib/firefox/libnssdbm3.so
#12 0x00007fffcf6eb12f in ?? () from /usr/lib/firefox/libsoftokn3.so
#13 0x00007fffcf6eb6f5 in ?? () from /usr/lib/firefox/libsoftokn3.so
#14 0x00007fffcf6d4321 in ?? () from /usr/lib/firefox/libsoftokn3.so
#15 0x00007fffcf6d746f in ?? () from /usr/lib/firefox/libsoftokn3.so
#16 0x00007ffff597120d in ?? () from /usr/lib/firefox/libnss3.so
#17 0x00007ffff5972261 in ?? () from /usr/lib/firefox/libnss3.so
#18 0x00007ffff598206e in PK11_ImportCert () from /usr/lib/firefox/libnss3.so
#19 0x00007fffe949d431 in ?? () from /usr/lib/firefox/libxul.so
#20 0x00007fffe67bc232 in ?? () from /usr/lib/firefox/libxul.so
#21 0x00007fffe6f1eeac in ?? () from /usr/lib/firefox/libxul.so
#22 0x00007fffe6f23c76 in ?? () from /usr/lib/firefox/libxul.so
#23 0x00007fffe9835da8 in ?? () from /usr/lib/firefox/libxul.so
#24 0x00007fffe9828cbe in ?? () from /usr/lib/firefox/libxul.so
#25 0x00007fffe9835af4 in ?? () from /usr/lib/firefox/libxul.so
#26 0x00007fffe9835ee9 in ?? () from /usr/lib/firefox/libxul.so
#27 0x00007fffe98365f2 in ?? () from /usr/lib/firefox/libxul.so
#28 0x00007fffe9b1a311 in ?? () from /usr/lib/firefox/libxul.so
#29 0x00007fffe7b12cf5 in ?? () from /usr/lib/firefox/libxul.so
#30 0x00007fffe7dba6b6 in ?? () from /usr/lib/firefox/libxul.so
#31 0x00007fffe7dc0498 in ?? () from /usr/lib/firefox/libxul.so
#32 0x00007fffe7dc0cda in ?? () from /usr/lib/firefox/libxul.so
#33 0x00007fffe7d9ff82 in ?? () from /usr/lib/firefox/libxul.so
#34 0x00007fffe7da3bae in ?? () from /usr/lib/firefox/libxul.so
#35 0x00007fffe7da3eae in ?? () from /usr/lib/firefox/libxul.so
#36 0x00007fffe8799edc in ?? () from /usr/lib/firefox/libxul.so
#37 0x00007fffe73c0177 in ?? () from /usr/lib/firefox/libxul.so
#38 0x00007fffe899c084 in ?? () from /usr/lib/firefox/libxul.so
#39 0x00007fffe899c3cb in ?? () from /usr/lib/firefox/libxul.so
#40 0x00007fffe7da0330 in ?? () from /usr/lib/firefox/libxul.so
---Type <return> to continue, or q <return> to quit---
#41 0x00007fffe7da3bae in ?? () from /usr/lib/firefox/libxul.so
#42 0x00007fffe878f8f2 in ?? () from /usr/lib/firefox/libxul.so
#43 0x00007fffe87b3545 in ?? () from /usr/lib/firefox/libxul.so
#44 0x00007fffe87b6554 in ?? () from /usr/lib/firefox/libxul.so
#45 0x00007fffe7d85a3f in ?? () from /usr/lib/firefox/libxul.so
#46 0x00007fffe7d85c94 in ?? () from /usr/lib/firefox/libxul.so
#47 0x00007fffe7d8a1c8 in ?? () from /usr/lib/firefox/libxul.so
#48 0x00007fffe87b3591 in ?? () from /usr/lib/firefox/libxul.so
#49 0x00007fffe87b3f70 in ?? () from /usr/lib/firefox/libxul.so
#50 0x00007fffe87b6291 in ?? () from /usr/lib/firefox/libxul.so
#51 0x00007fffe853096f in ?? () from /usr/lib/firefox/libxul.so
#52 0x00007fffe853259a in ?? () from /usr/lib/firefox/libxul.so
#53 0x00007fffe856e496 in ?? () from /usr/lib/firefox/libxul.so
#54 0x00007fffe85392dd in ?? () from /usr/lib/firefox/libxul.so
#55 0x00007fffe8575a72 in ?? () from /usr/lib/firefox/libxul.so
#56 0x00007fffe8575b47 in ?? () from /usr/lib/firefox/libxul.so
#57 0x00007ffff48d8fac in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#58 0x00007ffff1d91fa5 in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#59 0x00007ffff1da3fc1 in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#60 0x00007ffff1dac7f9 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#61 0x00007ffff1dad08f in g_signal_emit () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#62 0x00007ffff4a16c3c in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#63 0x00007ffff4a36dd3 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#64 0x00007ffff48d81e8 in gtk_main_do_event () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0
#65 0x00007ffff4445d92 in ?? () from /usr/lib/x86_64-linux-gnu/libgdk-3.so.0
#66 0x00007ffff1abb197 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#67 0x00007ffff1abb3f0 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#68 0x00007ffff1abb49c in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#69 0x00007fffe8590d6f in ?? () from /usr/lib/firefox/libxul.so
#70 0x00007fffe855a852 in ?? () from /usr/lib/firefox/libxul.so
#71 0x00007fffe855aa12 in ?? () from /usr/lib/firefox/libxul.so
#72 0x00007fffe67b54e5 in ?? () from /usr/lib/firefox/libxul.so
#73 0x00007fffe67b0498 in ?? () from /usr/lib/firefox/libxul.so
#74 0x00007fffe9385cd5 in ?? () from /usr/lib/firefox/libxul.so
#75 0x00007fffe965e09e in ?? () from /usr/lib/firefox/libxul.so
#76 0x00007fffe965eb20 in ?? () from /usr/lib/firefox/libxul.so
#77 0x00007fffe73ff615 in ?? () from /usr/lib/firefox/libxul.so
#78 0x00007fffe73ffc2f in ?? () from /usr/lib/firefox/libxul.so
#79 0x00007fffe73ffd9f in ?? () from /usr/lib/firefox/libxul.so
#80 0x00007fffe7a3f343 in ?? () from /usr/lib/firefox/libxul.so
#81 0x00007fffe7997068 in ?? () from /usr/lib/firefox/libxul.so
---Type <return> to continue, or q <return> to quit---
#82 0x00007fffe9835da8 in ?? () from /usr/lib/firefox/libxul.so
#83 0x00007fffe9828cbe in ?? () from /usr/lib/firefox/libxul.so
#84 0x00007fffe9835af4 in ?? () from /usr/lib/firefox/libxul.so
#85 0x00007fffe9835ee9 in ?? () from /usr/lib/firefox/libxul.so
#86 0x00007fffe9828cbe in ?? () from /usr/lib/firefox/libxul.so
#87 0x00007fffe9835af4 in ?? () from /usr/lib/firefox/libxul.so
#88 0x00007fffe9835ee9 in ?? () from /usr/lib/firefox/libxul.so
#89 0x00007fffe98365f2 in ?? () from /usr/lib/firefox/libxul.so
#90 0x00007fffe9b1a613 in ?? () from /usr/lib/firefox/libxul.so
#91 0x00007fffe73e7902 in ?? () from /usr/lib/firefox/libxul.so
#92 0x00007fffe73e6b33 in ?? () from /usr/lib/firefox/libxul.so
#93 0x00007fffe73e6b33 in ?? () from /usr/lib/firefox/libxul.so
#94 0x00007fffe73e7eb4 in ?? () from /usr/lib/firefox/libxul.so
#95 0x00007fffe8337b24 in ?? () from /usr/lib/firefox/libxul.so
#96 0x00007fffe83382d1 in ?? () from /usr/lib/firefox/libxul.so
#97 0x00007fffe6dc2004 in ?? () from /usr/lib/firefox/libxul.so
#98 0x00007fffe6e43ca6 in ?? () from /usr/lib/firefox/libxul.so
#99 0x00007fffe6bb9d7f in ?? () from /usr/lib/firefox/libxul.so
#100 0x00007fffe6bc1b6b in ?? () from /usr/lib/firefox/libxul.so
#101 0x00007fffe6bc345d in ?? () from /usr/lib/firefox/libxul.so
#102 0x00007fffe67b5625 in ?? () from /usr/lib/firefox/libxul.so
#103 0x00007fffe67b0498 in ?? () from /usr/lib/firefox/libxul.so
#104 0x00007fffe6bb2b91 in ?? () from /usr/lib/firefox/libxul.so
#105 0x00007fffe6b88c7d in ?? () from /usr/lib/firefox/libxul.so
#106 0x00007fffe8555de8 in ?? () from /usr/lib/firefox/libxul.so
#107 0x00007fffe95f84de in ?? () from /usr/lib/firefox/libxul.so
#108 0x00007fffe968a13f in ?? () from /usr/lib/firefox/libxul.so
#109 0x00007fffe968b17a in ?? () from /usr/lib/firefox/libxul.so
#110 0x00007fffe968b5f6 in ?? () from /usr/lib/firefox/libxul.so
#111 0x000055555555a745 in ?? ()
#112 0x0000555555559d5c in ?? ()
#113 0x00007ffff6d64830 in __libc_start_main (main=0x555555559cf0, argc=2, argv=0x7fffffffddf8,init=<optimized out>,
fini=<optimized out>,rtld_fini=<optimized out>, stack_end=0x7fffffffdde8) at ../csu/libc-start.c:291
#114 0x000055555555a079 in _start ()
(gdb)

Okay, it was causing a crash while adding certificate which gave me an hint that this bug will come under  crypto-core-security in Firefox. Moving forward i report this to Mozilla. However i noticed that if i create a new profile in FirefoxESR (i.e. go to "about:profiles", "create new profile"/"launch profile in new browser") and add the same certificate it didn't cause a crash.

So it seems like there's something specific to my profile that's causing this underflow, Moving further David Keeler and me analyze cert8.db file to check for the root cause of this bug.

Where cert8.db file consists of security certificates stored separately from the Operating System. sometimes the certificate store can become corrupted.
After taking a look on cert8.db looks like something caused my certificate database to be corrupted :(

Because the legacy certificate database implementation was written before the dawn of time, there are places where it's not very careful about its inputs. In particular, it looks like if some database metadata gets corrupted, ugly_split will do an unchecked subtraction and try to operate on data it thinks is very large:

h_page.c:485

        off = hashp->BSIZE;
        for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
            cino = (char *)ino;
            key.data = (uint8 *)cino + ino[n];
A           key.size = off - ino[n];
            val.data = (uint8 *)cino + ino[n + 1];
            val.size = ino[n] - ino[n + 1];
            off = ino[n + 1];

B           if (__call_hash(hashp, (char *)key.data, key.size) == obucket) {


At A, we have no guarantee that off >= ino[n], so at B we pass in a very large value for the size of the key.

Mozilla Security Team change risk from None to Moderate (sec-moderate) based on that this would require modifying the user's profile on-disk to exploit.

PS: I tried exploiting this using ncat with SSL but the session is not stable and it dies.

Issue Reported: 19-11-2017
Fixed Released: 05- 12-2017
Awarded with 750$ 


For everyone who might need a better understanding of how this bug works and how it can be exploited, read further.

My Assumption:
As stated in the blog, a corruption in cert8.db causes this crash, and every beginner in BOF knows crash is how we fuzz to create an exploit.
Since there is no check in the value of the variable 'off' any overwrite can make the value of 'off' to be set lower than ino[n] resulting in the crash.
Assuming 'hashp' is a pointer to a buffer size or memory address, a lower or negative value of 'off' may be result of getting higher memory address value from the stack thus setting key.size to much greater and when you have crashes and deals with memory there is high chances that this can be taken advantage to inject shell code into memory to execute.
For now what I tired was adding a shell code in h_page.c with a handler but established connection was not stable, I am sure a more experienced exploit writer can get a reverse shell by overwriting the cert8.db


Regards
Dhiraj

3 comments:

  1. Still dont understand , can you explain a bit more ...

    ReplyDelete
  2. But how come it didn't crash with new profiles ?

    ReplyDelete