TryHackMe — Library Walkthrough
Introduction
TryHackMe — Library Walkthrough
Introduction
In this walkthrough, I’ll be solving the Library machine from TryHackMe. This is a beginner-friendly Linux box that shows how small weaknesses can be chained together to gain full system compromise.

Enumeration
The first step in any machine is to identify what services are exposed. For this, I used Nmap to scan all ports and detect service versions.

nmap -sV -A -p- 10.48.159.239
- nmap → the network scanning tool used to discover open ports and services.
- -sV → probes open ports to identify the version of the service running on them.
- -A → enables aggressive scan features such as OS detection, version detection, script scanning, and traceroute.
- -p- → tells Nmap to scan all 65535 TCP ports instead of only the top common ones.
- 10.48.159.239 → the target machine IP address.
Result
22/tcp open ssh OpenSSH 7.2p2 Ubuntu
80/tcp open http Apache httpd 2.4.18 Ubuntu
The scan shows two open ports:
- Port 22 (SSH) running OpenSSH 7.2p2
- Port 80 (HTTP) running Apache 2.4.18
At this stage, the web server is the best place to start. Web applications often reveal usernames, files, directories, or credentials that can later be reused against services like SSH.
Web Enumeration
Since the target exposes an HTTP service, I opened the website in the browser to see what was running on it.
The site displayed a blog page titled:
Welcome to Blog — Library Machine
Even if a website looks simple, it is still worth enumerating for hidden directories and manually reviewing the content for usernames or useful information.

Directory Bruteforcing
To look for hidden paths, I used ffuf for directory enumeration.

ffuf -u http://10.48.159.239/FUZZ \
-w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
- ffuf → a fast web fuzzer commonly used for finding hidden directories, files, parameters, and virtual hosts.
- -u http://10.48.159.239/FUZZ → the target URL.
FUZZis the placeholder that ffuf will replace with each word from the wordlist. - -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt → the wordlist used for fuzzing. In this case, a common directory wordlist from DirBuster.
Result
The scan returned only one interesting directory:
/images
No admin panel, upload functionality, or backup directory was found from directory brute forcing.
Manual Review of the Website
Even though directory enumeration did not reveal much, manually reviewing the website content was still important. While exploring the blog, I noticed a username mentioned on the page:

meliodas
Why this matters
This is an important finding because usernames exposed on websites are often reused as valid system usernames. Since SSH is open on the machine, **meliodas** immediately becomes a strong candidate for an SSH login attempt.
At this point, we do not have a password yet, but we do have a valid username. That is enough to move to the next stage.
SSH Brute Force
Now that I had a likely valid username, I targeted the SSH service with Hydra to test a password list against the account.

hydra -l meliodas \
-P /usr/share/wordlists/rockyou.txt \
ssh://10.48.159.239
- hydra → a login brute-force tool that supports many protocols including SSH, FTP, HTTP, SMB, and others.
- -l meliodas → specifies a single username to test. In this case, the username discovered from the blog.
- -P /usr/share/wordlists/rockyou.txt → provides a password wordlist.
rockyou.txtis a very common password list used in CTFs and labs. - ssh://10.48.159.239 → tells Hydra to attack the SSH service on the target machine.
Hydra successfully recovered valid credentials:
[22][ssh] host: 10.48.159.239 login: meliodas password: iloveyou1
Credentials Found
- Username:
meliodas - Password:
iloveyou1
This confirms that the username found on the website is also a valid SSH account and that the account is protected by a weak password.
Now that we have valid credentials, we can move from remote enumeration to initial shell access.
Initial Access
Using the credentials recovered by Hydra, I logged in over SSH.
ssh meliodas@10.48.159.239
- ssh → the Secure Shell client used to remotely connect to a machine.
- meliodas@10.48.159.239 → logs in to the target as the user
meliodas.
When prompted for the password, I entered:
iloveyou1
After logging in successfully, I listed the contents of the home directory to see what files were available.
ls
- ls → lists files and directories in the current directory.
bak.py
user.txt
Two files are immediately visible:
user.txt→ likely the user flagbak.py→ a Python script that may become interesting later during privilege escalation
Reading the User Flag
The next step was to read the user flag.

cat user.txt
- cat → displays the contents of a file directly in the terminal.
Result
6d488cbb3f111d135722c33cb635f4ec
At this point, user-level access is complete. The next task is to escalate privileges to root.
Privilege Escalation Enumeration
After gaining a foothold on a Linux machine, one of the first commands I always run is:
sudo -l
This checks whether the current user can run any commands as another user (usually root) through sudo.

- sudo → runs a command as another user, usually root.
- -l → lists the commands the current user is allowed to run via sudo.
Result
(ALL) NOPASSWD: /usr/bin/python* /home/meliodas/bak.py
Understanding the Sudo Misconfiguration
This line is the key to privilege escalation.
Let’s break it down:
(ALL) NOPASSWD: /usr/bin/python* /home/meliodas/bak.py
- (ALL) → the command can be executed as any user, including root.
- NOPASSWD → the command can be run without entering a password.
- **/usr/bin/python*** → any Python interpreter matching that path can be used, such as
python,python2, orpython3. - /home/meliodas/bak.py → the script that sudo allows us to run.
In simple terms, this means:
The user meliodas is allowed to run a Python interpreter as root on the script /home/meliodas/bak.py without entering a password.
That is extremely dangerous if the script can be modified or replaced.
Checking the Script Permissions
To understand whether we can abuse this, I checked the file permissions.

ls -la
- ls -la
- -l → shows long listing format, including permissions, ownership, and timestamps.
- -a → includes hidden files as well.
Result
-rw-r--r-- 1 root root 353 bak.py
At first glance, this might look safe because the file is owned by root.
But file ownership is not the full story.
Why This Is Still Exploitable
Although bak.py is owned by root, it is stored inside the user’s home directory. If the directory permissions allow meliodas to write inside it, then the user can delete the existing file and create a new file with the same name.
That means the attack path becomes:
- Delete the original
bak.py - Replace it with a malicious Python script
- Run it using the allowed sudo command
- The script executes as root
This is a classic example of a dangerous sudo rule involving a script in a user-controlled location.
Exploitation
To exploit this, I removed the original bak.py and replaced it with a simple Python payload that spawns a shell.
Step 1: Remove the original script
rm bak.py
- rm → removes a file.
- Here, it deletes the original
bak.pyso that we can replace it with our own malicious version.
Step 2: Create a malicious Python script
echo 'import os; os.system("/bin/bash")' > bak.py

- echo ‘…’ → prints the string inside the quotes.
- > bak.py → redirects the output into a file named
bak.py, creating or overwriting it.
The payload inside the file is:
import os
os.system("/bin/bash")
What this Python payload does
- import os → imports Python’s
osmodule, which allows interaction with the operating system. - os.system(“/bin/bash”) → runs
/bin/bashas a system command.
Because we will run this script through the sudo rule, the Bash shell launched by the script will execute with root privileges.
Step 3: Execute the malicious script as root
Now that the script has been replaced, I used the allowed sudo command to execute it.

sudo /usr/bin/python3 /home/meliodas/bak.py
Command Explanation
- sudo → executes the command with elevated privileges according to the sudo rule.
- /usr/bin/python3 → the Python interpreter being used.
- /home/meliodas/bak.py → the malicious script we just created.
Because this exact command matches the sudo rule, it runs as root without asking for a password.
Result
root@ubuntu:~#
We now have a root shell.
Reading the Root Flag
With root access, the final step is to retrieve the root flag from the root user’s home directory.

cd /root
cat root.txt
Result
e8c8c6c256c35515d1d344ee0488c617
Full Attack Path Summary
The complete compromise chain for this room was:
- Enumerate the target with Nmap and identify SSH and HTTP services
- Inspect the website and discover the username
meliodas - Brute-force SSH using Hydra and recover the password
iloveyou1 - Log in over SSH as
meliodas - Enumerate sudo privileges using
sudo -l - Identify the dangerous Python sudo rule
- Replace
bak.pywith a malicious Python script - Execute the script via sudo
- Obtain a root shell and read the root flag
Conclusion
The Library machine is a simple but effective room for practicing the basics of Linux compromise. The path to root is built from three mistakes:
- a username exposed through the website
- a weak SSH password
- an unsafe sudo rule involving a Python script in a user-controlled location
None of these issues are complicated on their own, but together they lead to full compromise of the machine.
For beginners, this room is excellent practice for building the habit of enumerate → analyze → exploit → escalate rather than rushing straight into attacks.
메타데이터
- post_id
- 8cf738514dc2
- slug
- tryhackme-library-walkthrough-8cf738514dc2
- url
- https://medium.com/@siyonrai2/tryhackme-library-walkthrough-8cf738514dc2
- canonical_url
- https://medium.com/@siyonrai2/tryhackme-library-walkthrough-8cf738514dc2
- author_url
- https://medium.com/@siyonrai2
- status
- ok
- fetched_at
- 2026-07-26 02:36:47