In this post, I would like to share a walkthrough of the Bookworm Machine from Hack the Box.
This room will be considered an Insane machine on Hack the Box
What will you gain from the Bookworm machine?
For the user flag, you will need a sophisticated exploit chain by leveraging cross-site scripting, insecure upload, and insecure direct object reference vulnerabilities. This orchestrated approach allows for the identification of an HTTP endpoint with file download capabilities. Within this endpoint, a directory traversal attack is exploited when multiple files are requested, enabling the retrieval of arbitrary files in the resulting Zip archive. This exploitation is then utilized to extract database credentials, which conveniently double as SSH credentials on the system. The subsequent user operates a development web server responsible for managing ebook format conversions. This functionality is manipulated by employing symlinks to achieve arbitrary write access. Subsequently, an SSH public key is written, facilitating unauthorized access
As for the root flag, you need an SQL injection vulnerability within a script responsible for label creation to be exploited. This enables PostScript injection, providing the capability to read and write files at the root level, completing the privilege escalation chain.
For those who want to learan or improve CyberSecurity skills especially Red Teaming and Blue Team, You can use the link https://affiliate.hackthebox.com/gnfp67dzy7p0 to support me
Academy link can be found https://affiliate.hackthebox.com/wanmohdariffwanmohdrosdi6259vv
Information Gathering on Bookworm Machine
Once we have started the VPN connection which requires a download from Hackthebox, we can start the information gathering on the machine by executing the command nmap -sC -sV -p- <IP Address> -PN
┌─[darknite@parrot]─[~/Document/htb/bookworm]
└──╼ nmap -sC -sV 10.10.11.215 -oA intial
# Nmap 7.92 scan initiated Mon May 29 04:16:35 2023 as: nmap -sC -sV -oA initial 10.10.11.215
Nmap scan report for 10.10.11.215
Host is up (0.17s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 81:1d:22:35:dd:21:15:64:4a:1f:dc:5c:9c:66:e5:e2 (RSA)
| 256 01:f9:0d:3c:22:1d:94:83:06:a4:96:7a:01:1c:9e:a1 (ECDSA)
|_ 256 64:7d:17:17:91:79:f6:d7:c4:87:74:f8:a2:16:f7:cf (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://bookworm.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)
2710/tcp filtered sso-service
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon May 29 04:16:58 2023 -- 1 IP address (1 host up) scanned in 23.50 seconds
Let’s access the website interface
However, the website interface looks very normal, and I noticed that there are login functions that we can take advantage of.
We are required to register a new account on the website.
At last, we managed to access the dashboard by using the credentials that we created earlier.
Therefore, let’s try to buy a new book by clicking the “Add to Basket” button.
The payload of adding the book into payment will look something like the above.
It will look something like the above.
As a result, we should upload and update the avatar on my profile picture.
The request and response on the burpsuite will look something like as above.
Let’s upload some random picture
The payload on burpsuite as above
From the cookie token, we managed to retrieve an “id” for the profile. However, the ID will be different when creating a new account
Let’s start our Python server.
Therefore, let’s execute our XSS attack on the edit column
Boom! The XSS attack managed to give us a response on the Python server
const { sequelize, User, Book, BasketEntry, Order, OrderLine } = require("./database");
When trying to analyze the index.js source code, we found a path that might provide us with some useful information.
const sequelize = new Sequelize(
process.env.NODE_ENV === "production"
? {
dialect: "mariadb",
dialectOptions: {
host: "127.0.0.1",
user: "bookworm",
database: "bookworm",
password: "FrankTh3JobGiver",
},
logging: false,
}
: "sqlite::memory::"
);
Inside the database file, we managed to find a password that can be used to access machine as frank ( i just guess from the password structure)
We can read the user flag by typing the “cat user.txt” command.
Escalate to Root Privileges Access
There are a few localhost ports that we can investigate further.
Therefore, let’s do some port-forwarding with the port 3001
The website interface will look something like the above
SSH to Neil Access on the machine
We need to create a pdf file so that we can upload the malicious file into the application
Aside from that, we also need to create a ssh key on our attacker machine
Therefore, we need to redirect the file to the SSH path
We can change the content on the file which we can insert our SSH public key into the application
Finally, we managed to access the machine as Neil
The only SUID binary that we can find is genlabel as shown in the screenshot above.
neil@bookworm:~$ cat /usr/local/bin/genlabel
#!/usr/bin/env python3
import mysql.connector
import sys
import tempfile
import os
import subprocess
with open("/usr/local/labelgeneration/dbcreds.txt", "r") as cred_file:
db_password = cred_file.read().strip()
cnx = mysql.connector.connect(user='bookworm', password=db_password,
host='127.0.0.1',
database='bookworm')
if len(sys.argv) != 2:
print("Usage: genlabel [orderId]")
exit()
try:
cursor = cnx.cursor()
query = "SELECT name, addressLine1, addressLine2, town, postcode, Orders.id as orderId, Users.id as userId FROM Orders LEFT JOIN Users On Orders.userId = Users.id WHERE Orders.id = %s" % sys.argv[1]
cursor.execute(query)
temp_dir = tempfile.mkdtemp("printgen")
postscript_output = os.path.join(temp_dir, "output.ps")
# Temporary until our virtual printer gets fixed
pdf_output = os.path.join(temp_dir, "output.pdf")
with open("/usr/local/labelgeneration/template.ps", "r") as postscript_file:
file_content = postscript_file.read()
generated_ps = ""
print("Fetching order...")
for (name, address_line_1, address_line_2, town, postcode, order_id, user_id) in cursor:
file_content = file_content.replace("NAME", name) \
.replace("ADDRESSLINE1", address_line_1) \
.replace("ADDRESSLINE2", address_line_2) \
.replace("TOWN", town) \
.replace("POSTCODE", postcode) \
.replace("ORDER_ID", str(order_id)) \
.replace("USER_ID", str(user_id))
print("Generating PostScript file...")
with open(postscript_output, "w") as postscript_file:
postscript_file.write(file_content)
print("Generating PDF (until the printer gets fixed...)")
output = subprocess.check_output(["ps2pdf", "-dNOSAFER", "-sPAPERSIZE=a4", postscript_output, pdf_output])
if output != b"":
print("Failed to convert to PDF")
print(output.decode())
print("Documents available in", temp_dir)
os.chmod(postscript_output, 0o644)
os.chmod(pdf_output, 0o644)
os.chmod(temp_dir, 0o755)
# Currently waiting for third party to enable HTTP requests for our on-prem printer
# response = requests.post("http://printer.bookworm-internal.htb", files={"file": open(postscript_output)})
except Exception as e:
print("Something went wrong!")
print(e)
cnx.close()
neil@bookworm:~$
The source code of the script can be seen in the text above.
From my understanding, we can play with the SQL command which we can outfile our SSH public key into the machine
At last, we can access the machine as root
Metasploit method on the bookworm machine
Firstly, we can open the msfconsole as shown below
In this activity, we will be using the exploit on the chrome_debugger to gather the payload
We are required to fill in the information above in order for the payload to work
As a result, we will insert as shown above.
The remote port is always changing all the time so we need to change accordingly.
We managed to get a root flag by using this method too.
No responses yet