It's more trivial to escape a full install chroot than escaping from a frugal install chroot

For discussions about security.
Post Reply
s243a
Posts: 501
Joined: Mon Dec 09, 2019 7:29 pm
Has thanked: 90 times
Been thanked: 37 times

It's more trivial to escape a full install chroot than escaping from a frugal install chroot

Post by s243a »

I don't claim here that running puppy in frugal install mode provides a significant security advantage over a full install for the purposes of containing a process to a chroot jail but it is interesting nonetheless that a puppy running via frugal install will thwart the most naive chroot escape attempts. rufwoof, in one post made the comment that most attackers don't have a lot of skill so perhaps the ultra-naive hacker is out there that will get thwarted by a frugally installed puppy. So why is this so?

Well first some background. I found the following interesting:

(The smallest part, in fact. And you should be aware that root can always
get out of a chdir() if he just has enough tools - and the tools aren't
even very big. "mknod" + "mount" will do it even in the absense of a way
to add binaries, as will /proc access).

http://lkml.iu.edu/hypermail//linux/ker ... /0185.html

and so for curiosity I decided to search for chroot escapes using mknod and mount and the first thing I found was a briliantly naive attempt to escape out of a chroot:
https://gist.github.com/0xquad/7ea47ccf8e2c055748e7

It's brilliant because someone like me that has a hard time reading linux c code is able to follow it. It's naive because as we will see it not only assumes a full install but also assumes that the root will be at the top level of the device file system and only in one of the first two partitions.

So here is what it does, It essentially only looks at the first two partiations of the first two hard drives via this command:

Code: Select all

dev_t devs[] = {makedev(8, 0), makedev(8, 1), makedev(8, 2)};

https://gist.github.com/0xquad/7ea47ccf ... esc-c-L137

the function makedev takes the major and minor device number. These are given in columns 5 and 6 of the following table:

Code: Select all

brw-rw----    1 root     disk       8,   0 Mar 15  2002 sda
brw-rw----    1 root     disk       8,   1 Mar 15  2002 sda1
brw-rw----    1 root     disk       8,   2 Mar 15  2002 sda2

https://tldp.org/LDP/Linux-Filesystem-H ... l/dev.html

from which we see that the devices are sda, sda1 and sda2 (i.e. the first two partitions of the first hard drive). We make a directory to mount the device or a partion of the device:

Code: Select all

mkdir(mnt, 0755);

https://gist.github.com/0xquad/7ea47ccf ... sc-c-L144]

and then we try to mount the device or partion at this directory:

Code: Select all

ret = mount_fs(devs[i], fs_types[j], mnt);

https://gist.github.com/0xquad/7ea47ccf ... esc-c-L148

If this succeeds then we check to see if the directory has the following folders

Code: Select all

char *dirs[] = { "proc", "dev", "home", "usr", "var" };

https://gist.github.com/0xquad/7ea47ccf ... esc-c-L117

What I don't understand is why that stat command should throw an error if the directory exists:

Code: Select all

int isrootfs(const char *mnt)
...
err |= stat(path, &st);
...
return err;

https://gist.github.com/0xquad/7ea47ccf ... esc-c-L115

Code: Select all

int mount_escape()
...
if (isrootfs(mnt)) {
...
 ret = shell();
 }
 

https://gist.github.com/0xquad/7ea47ccf ... esc-c-L150

The return value of stat is as follows:

Code: Select all

On success, the functions return zero, and on error, −1 is returned and errno is set appropriately.

https://en.wikipedia.org/w/index.php?ti ... =956142916

So it looks to me that the code will only return a shell if one of the stat system calls fails (i.e. returns a -1). Since a true value in C is any non-zero value. This seems wrong to me, but I'm not an expert at c programming in linux.

s243a
Posts: 501
Joined: Mon Dec 09, 2019 7:29 pm
Has thanked: 90 times
Been thanked: 37 times

Re: It's more trivial to escape a full install chroot than escaping from a frugal install chroot

Post by s243a »

Here's some further reading about chroot escapes:

http://www.unixwiz.net/techtips/chroot-practices.html
https://filippo.io/escaping-a-chroot-jail-slash-1/

The first link notes that most escapes require root permission. The example in my first post uses the makedev command which likely requires root permission. One suggestion is to use the following command to drop root premissions:

Code: Select all

setXXuid(nonroot)

http://www.unixwiz.net/techtips/chroot-practices.html
https://people.eecs.berkeley.edu/~daw/p ... enix02.pdf

user1111

Re: It's more trivial to escape a full install chroot than escaping from a frugal install chroot

Post by user1111 »

s243a wrote: Sun Nov 29, 2020 8:10 am

I don't claim here that running puppy in frugal install mode provides a significant security advantage over a full install for the purposes of containing a process to a chroot jail but it is interesting nonetheless that a puppy running via frugal install will thwart the most naive chroot escape attempts.

Multi-session save style is the better choice of frugal IMO. In Fatdog for instance each time you click save it just adds another sfs of the changes to the set of all prior/past saves sfs's - which provides a audit-trail. Less relevant for OS/system (in Fatdog you can boot, delete all of the multi... save files and then click save - to consolidate them all into one), but for data that's great. Keep OS and data separate, and when that data is also using a 'frugal' (multi-session) type layering its very much like incremental backups. Your data server could be a Fatdog multi-session, and run any other Puppy for your desktop system, personally I use Fatdog for both.

Approach security from a perspective of 'when' root is compromised, and the damage limitation measures you have in place at that time. How quickly you can recover from that - such as OS recovery via a simple reboot and data security via disconnected backups. Combined with being thoughtful when doing sensitive transactions, such as rebooting into a known 'clean' system prior to going direct to your banks web site, nowhere else before or after (shutdown when done to clear out all fingerprints).

Across all of the millions of lines of code and thousands of programs/libs/modules bugs will occur/exist and where some of those flaws will have enabled systems to be compromised at some points in time. Eradication of persistence and maintaining data integrity are fundamentally the key factors.

Post Reply

Return to “Security”