[ntp:security] Critical vulnerabilities in ntpd

Danny Mayer mayer at ntp.org
Fri Sep 12 20:13:00 UTC 2014


Hi Stephen,

We are looking at the issues that you have identified. Since there are a
number of places to look at it will take a bit of time to get through
them all.

Danny

On 9/8/2014 3:00 PM, Stephen Röttger wrote:
> Hi,
> 
> 
> I identified a few security vulnerabilities in the latest stable version
> of ntpd (v4.2.6p5), including a critical buffer overflow that leads to
> remote code execution on common configurations.
> 
> I attached a detailed description to this message which will help you
> confirm and address the vulnerabilities. Please let me know if anything
> is unclear or needs further explanation.
> 
> 
> Please confirm at your earliest convenience that you have received this
> vulnerability report. We will gladly work with you so you can
> successfully confirm and reproduce this issue.
> 
> 
> Note that we consider this a critical vulnerability, and per our
> Vulnerability Disclosure process we may help protect customers by
> publicly disclosing some information on the vulnerability within 90 days
> of this report.
> 
> 
> Once you have reproduced the issue, we’d appreciate to learn your
> expected timeline for a security update to be released. With any fix,
> please give credit for identifying the vulnerability to “Stephen
> Röttger” of the Google Security Team.
> 
> 
> Don’t hesitate to let us know if you have any questions!
> 
> ========= Vulnerability details =========
> 
> A description of the identified vulnerabilities follows below. The
> buffer overflow in <ctl_putdata> leads to remote code execution on
> common configurations.
> To exploit this you need to be authenticated with a controlkey. However,
> ntpd will create a default 4 byte requestkey with keyid 65535 in
> <config_auth>, for which the random number generator was seeded with a
> 32 bit seed.
> Random values leak in normal time responses through the receive
> timestamp and can be used to brute force the seed offline and acquire
> the key. If ntpd was just restarted, I was able to brute force the
> correct seed with a naive single core implementation in ~30 minutes on
> my laptop.
> The requestkey can then be used to add the keyid 65535 as a controlkey
> through a private mode packet. Note that common configurations set
> restrictions to allow these packets only from localhost but this can be
> bypassed by spoofing an IPv6 packet with source ::1, which will be let
> through by Linux and OS X (IPv4 packets with source 127.0.0.1 are
> dropped on the other hand).
> 
> ntpd/ntp_crypto.c:792 <crypto_recv>(buffer overflow)
> 
> if (vallen == (u_int)EVP_PKEY_size(host_pkey)) {
> 
> if (RSA_private_decrypt(vallen,
> Â Â (u_char *)ep->pkt,
> Â Â (u_char *)&temp32,
> Â Â host_pkey->pkey.rsa,
> Â Â RSA_PKCS1_OAEP_PADDING) <= 0) {
> 
> This code is part of the NTP autokey protocol. The client sends a RSA
> public key to the server, which encrypts a 32bit token and sends it
> back. This code handles the server response on the client side and
> decrypts the token into the 32 bit integer temp32. However, the
> decrypted cleartext can be up to (keysize/8)-42 in size (e.g. 214 bytes
> for a 2048 bit key).
> 
> Two things make this less bad: 1) you need to have autokey enabled
> explicitly by generating a key with ntp-keygen and adding something like:
> 
> crypto pw serverpassword
> keysdir /etc/ntp
> 
> to your config. And 2) by default ntp-keygen generates 512 bit keys
> which results in an 18 byte overwrite and, at least on the ubuntu ntp
> package, this doesn’t seem to overwrite anything valuable on the stack.
> 
> 
> ntpd/ntp_control.c:1027 <ctl_putdata>(buffer overflow, needs privileges)
> if (dlen + overhead + datapt > dataend) {
> /*
> * Not enough room in this one, flush it out.
> */
> ctl_flushpkt(CTL_MORE);
> }
> memmove((char *)datapt, dp, (unsigned)dlen);
> 
> Overflow if dlen is bigger than datapt. This happens e.g. when it is
> called from <configure+69> with a big error message, which can be
> triggered by chaining multiple error messages after each other. Through
> Â the <configure+69> codepath, code execution is unlikely since you have
> limited control over the data that is written but it can be used as an
> information leak.
> 
> Another code path is through <read_variables> after setting a big
> variable with a setvar config line. This will lead to an information
> leak and code execution as described before.
> 
> 
> ntpd/ntp_control.c:2095 <ctl_getitem>(possible infoleak)
> 
> *data = buf;
> 
> This function passes a pointer to a local buffer back to the calling
> function. If another function is called before the data is used, the
> contents can be overwritten and it might result in an information leak.
> 
> 
> ntpd/ntp_control.c:2495 <configure>(buffer overflow, needs privileges)
> 
> data_count = reqend - reqpt;
> memcpy(remote_config.buffer, reqpt, data_count);
> 
> A buffer overflow from the user-provided packet into a global variable.
> For this code path you need to be able to send authenticated
> configuration packets.
> 
> 
> ntpd/ntp_proto.c:946 <receive>(missing return on error)
> 
> if (is_authentic == AUTH_ERROR) {
> fast_xmit(rbufp, MODE_ACTIVE, 0,
> restrict_mask);
> sys_restricted++;
> }
> 
> A new connection from a symmetric active peer with a broken signature
> will send an error reply to the client but then use the codepath of a
> valid packet afterwards, which includes adding him as a peer. Not sure
> if this is an issue though, since I couldn’t find a codepath in which
> the peer isn’t removed again from the list.
> 
> 
> util/ntp-keygen.c:724 <gen_md5>(keys without entropy)
> 
> ntp_srandom((u_long)epoch);
> 
> The symmetric MD5 keys generated by ntp-keygen have no entropy at all.
> They are generated with a custom random number generator that is only
> seeded with the number of seconds since 1970. Even if we can’t
> estimate the creation time of the keys this leaves us with 2^30 for
> brute forcing.
> 
> 
> ntpd/ntp_config.c:1689 <config_auth>(weak default key)
> 
> int rankey;
> rankey = ntp_random();
> req_keytype = NID_md5;
> req_hashlen = 16;
> MD5auth_setkey(req_keyid, req_keytype,
> Â Â Â (u_char *)&rankey, sizeof(rankey));
> authtrust(req_keyid, 1);
> 
> If no auth key is set in the config, ntpd will generate a random key on
> the fly. There are two problems with this: 1) the generated key is 31
> bit in size, 2) it uses the weak ntp_random function, which is seeded
> with a 32 bit value and can only provide 32 bit of entropy.
> 
> 
>       Missing validation of vallen that leads to various info leaks
> 
> 
> ntpd/ntp_crypto.c:571 <crypto_recv>(buffer overread)
> 
> memcpy(peer->subject, ep->pkt, vallen);
> 
> ntpd/ntp_crypto.c:1162 <crypto_xmit>(buffer overread, non-exploitable)
> 
> memcpy(certname, ep->pkt, vallen);
> 
> vallen might be greater than the size of the packet. In the first case,
> peer->subject might be sent back to the client until the first null byte
> through a CTL_OP_READVAR control packet (if this is allowed on the
> interface) leading to an information leak. The second case doesn’t
> leak anything though, since certname is just compared against the name
> of the server’s cert.
> 
> 
> ntpd/ntp_crypto.c:1559 <crypto_encrypt>(possible infoleak)
> 
> len = ntohl(ep->vallen);
> ptr = (u_char *)ep->pkt;
> pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, len);
> 
> ntpd/ntp_crypto.c:2959 <cert_sign>(possible infoleak)
> 
> ptr = (u_char *)ep->pkt;
> if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
> 
> The cert is created with a length greater than the packet in both cases,
> possible information leak.
> 
> 
> ntpd/ntp_crypto.c:2117 <crypto_bob>(possible infoleak)
> 
> len = ntohl(ep->vallen);
> if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
> 
> Same with a bignum, possible information leak.
> 
> 
> ntpd/ntp_crypto.c:1461 <crypto_verify>(integer overflow, probably
> non-exploitable)
> 
> i = (vallen + 3) / 4;
> siglen = ntohl(ep->pkt[i++]);
> if (len < VALUE_LEN + ((vallen + 3) / 4) * 4 + ((siglen + 3) /
> 
> 4) * 4)
> 
> A vallen of UINT_MAX-2will result in i==0 and pass the length check. As
> far as I can tell, this doesn’t lead to any memory corruption and
> bypassing the cryptography is not severe since the autokey protocol was
> already shown to be broken.
> 
> 
> As mentioned before, if anything is unclear please let me know.
> 
> Best regards,
> 
> 
> Stephen Röttger
> 
> Google Security Team
> 
> 
> _______________________________________________
> security mailing list
> security at lists.ntp.org
> http://lists.ntp.org/listinfo/security
> 




More information about the security mailing list