
Week 2. Intuition
TL;DR
This is an Ubuntu 22.04 machine used for bug reporting via web forms. We can gain access to the web application admin dashboard by stealing cookies via XSS payloads. Then we exploit CVE-2023-24329 in Python-URLlib 3.11 to explore the file system and find an SSH private key which allows obtaining the user flag. Regarding escalation, first we move laterally to another user, then we do reversing on a custom binary to discover it is vulnerable to command injection.
KEYWORDS
XSS, CVE-2023-24329, Python-URLlib 3.11, Hashcat mask attack, Ghidra, reversing, command injection.
REFERENCES
https://www.cvedetails.com/cve/CVE-2023-24329/
ENUMERATION
Port scan.
> nmap $target -p- --min-rate=5000 -Pn --open --reason
Starting Nmap 7.93 ( https://nmap.org ) at 2024-04-28 17:04 EDT
Nmap scan report for 10.10.11.15
Host is up, received user-set (0.036s latency).
Not shown: 57729 closed tcp ports (conn-refused), 7804 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
Nmap done: 1 IP address (1 host up) scanned in 15.30 secondsEnumerate the open ports.
Fuzz for subdomains.
USER
Add to hosts file. Navigate to http://report.comprezzor.htb and click on "Report bug" (you'll need to sign up a new account).
The report submission form is vulnerable to XSS in both "Title" and "Description" boxes. Insert this payload to steal a cookie.
A cookie encoded in base64 is received on the listener, after decoding it we see it belongs to user adam
Use the cookie to login as adam and navigate to http://dashboard.comprezzor.htb, a list of reported bugs comes into view.
Click on each report ID to browse the incident data.
The report will be read by the admin as long as priority is set to 1. Adam has permission to change priorities so using his credentials (i.e. his cookie) we will send another report with the same XSS payload. Then set the priority to 1, it will be read by the admin and we will be able to steal admin's cookie.
Shortly after, admin's cookie is received on the listener.
Use the cookie to log in as admin, now a new functionality to generate PDFs is enabled.
The application takes a URL and converts its contents to PDF. Start an HTTP server and enter your IP in the URL field, capture the traffic with Wireshark and inspect it. In the HTTP headers we see the host is using the library python-urllib 3.11
There is a CVE-2023-24329 (https://www.cvedetails.com/cve/CVE-2023-24329/) affecting this version. Description reads: "Attackers can bypass blacklisting methods by supplying a URL that starts with blank characters".
Let's try using this payload file:///etc/os-release. Note there is with a blank space at the beginning as indicated in the CVE description.
The application dumps the OS info, so the vulnerability is confirmed.
Let's take advantage of this and enumerate the file system to find useful info. First, list the running process (remember there is a blank space at the beginning of the payloads).
Inspect the application source code.
We see calls to Python libraries. Let's inspect all of them.
In the last one (dashboard.py) we find FTP credentials for user ftp_admin
Let's see what is inside the FTP.
The note.txt is a welcome email from Adam containing the passphrase for the attached private key private-8297.key
To find out the username linked to this private key, just generate the correspondent public key and the user name will be added at the end of the resulting key.
Use the private key to open an SSH session in the host.
Which can be used to retrieve the user flag.
ROOT
Start from the low-priv SSH session and take the opportunity to enumerate the user and the system.
Enumerate local connections, there is an internal FTP server running.
Enumerate local users, we find a new user called lopez
Navigate to /var/www/app/blueprints/auth, there is an SQLite database stored there, browse its contents.
These are credentials for the internal FTP server. Crack Adam's hash (module 30120).
Connect to FTP using Adam's credentials. Inside, we find 2 files, runner1.c and run-tests.sh. This is the code of the first one.
In the source code we find a hardcoded MD5 hash 0feda17076d793c2ef2870d7427ad4ed which apparently is used to launch Ansible playbooks.
Let's se what is inside the shell script.
Here we see an incomplete password UHI75GHI****. Assuming the MD5 hash belongs to the incomplete password, we are able to crack the complete password using a Hashcat mask attack.
Take note and continue enumerating the file system. There is a directory in /opt/runner2 but current user does not have permissions.
We are going to need to move laterally to another user, and user lopez is the only possibility left. In the path /var/log/suricata there are several logs compressed in .gz, let's hunt for passwords.
Move laterally to lopez and verify he has access to directory /opt/runner2. We also discover he is a sudoer.
Inside the /opt/runner2 directory we find a binary called runner2
We have already found before the source code for runner1, but not for runner2, so there is no other option but to do reversing of this file.
Decompile runner2 with Ghidra and inspect the main() function. Here we can draw some conclusions.
The application takes
role_fileandauth_codeas arguments.auth_codeis sent to functioncheck_auth()as argument.Application expects an "action" called "install".
role_fileis sent to functioninstallRole()as argument.
Continue and inspect the 2 functions check_auth() and installRole()
In check_auth() we see the auth_code is with the MD5 hash we found before. So there is a high probability this key is the password we have already cracked.
Now let's inspect the installRole() function.
First, the function checks if the file is in .tar format. Secondly, we see the application takes role_file and passes it to the ansible-galaxy binary. Since we control this role_file parameter and it is used without sanitization, this function may be vulnerable to command injection.
To summarize, the app takes a user JSON as input, and it looks inside it for role_file and auth_code. The first one must be in .tar format, the path to this file is not sanitized and therefore the function is vulnerable to command injection. To execute this vulnerable installRole() function we have to select the "install" action. Finally, the auth_code is needed to execute the binary, and it is the password we cracked before.
Bearing this info in mind, let's prepare the attack. First create a .json including a path to a .tar file. To exploit the command injection we concatenate a command (using a semicolon ";") in the file name.
Now create a .tar file containing whatever content, for example, the JSON itself. Make sure it is named after the command injection payload we used in the JSON file.
Finally, execute the binary with sudo
You are root.
Last updated