[ntp:security] [Bug 2655] Multiple vulnerabilities in ntpd

bugzilla-daemon at ntp.org bugzilla-daemon at ntp.org
Tue Sep 9 19:55:22 UTC 2014


http://bugs.ntp.org/show_bug.cgi?id=2655

--- Comment #1 from Stephen Röttger <stephen.roettger at gmail.com> 2014-09-09 19:55:22 UTC ---
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-2 will 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.

-- 
Configure bugmail: http://bugs.ntp.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


More information about the security mailing list