OTW Bandit CTF 🚩 Writeup - Part 2 - Levels 13 to 22

See all the bandit writeups for the other levels.

Coffee? ✅

Workout? ✅

Laptops? ✅


Then let’s goooooo

here we go again



So why am I writing it up?

  1. I want to be sure that I understood how I solved the level.
  2. I want to be sure that I can explain my solution to other people.
  3. If someone is stuck and wants some help to continue, they can do so quickly.

These challeges can be frustrating. While I think that a little frustration is good (especially in CTFs), I hope this guide will cause someone who was almost discouraged from trying/continuing the challenge to carry on. If you’re one of these people - don’t give up! You can do this 💪🏽

spoiler alert

Also, I will try to avoid posting the passwords. If you do see a password that I forgot to omit please let me know!

Level 13 -> Level 14

The first thing you see is a file called sshkey.private and the contents are these:

ssh key

After reading a little about how SSH works, the gist for this challenge is that if you have someone’s private key (in this case, bandit14’s private key file), you can login as him if the server has authorized his public key. So, now let’s get to business: a quick man ssh and then search for the word private by writing /private:

    -i identity_file
      Selects a file from which the identity (private key) for public key authentication is read.

Finally, let’s log in (Shoutout to ScreenToGif):


Level 14 -> Level 15

The level guide tells us the following: The password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost..

Let’s first make sure someone is indeed listening and in which protocol, using nmap:

nmap result

We see 30000/tcp which is good. It means that there’s a server listening on port 30000 with the TCP protocol. We don’t know what the server is really expecting, so let’s try to talk to it and see what happens. We can use the nc command to do that. Again, the example is straight out of the man nc page:

nc wrong password

OK! So we have a server that’s listening for text-based input listening on port 30000/tcp and we need to submit the user’s current password to the server. I admit I was stuck on this for a while until my wife reminded me the previous instructions we got which told us that the password was stored in /etc/bandit_pass/bandit14 😅 So, to solve this we needed to pass the contents of that file to the server:

nc right passowrd

Level 15 -> Level 16

This level is very similar to the previous one, but you need to connect using SSL. Luckily, openssl has a handy utility just for that: s_client. Just run openssl s_client -connect localhost:30001 and paste the password and you’re good!

Level 16 -> Level 17

We need to find a specific server that’s listening on TLS between ports 31000 and 32000. Just running nmap localhost won’t do because nmap only scans some known ports and not the range we need. So we’ll have to use the -p flag to specify ports:


We got 2 servers. Let’s try to connect to them using SSL, just like the last stage: openssl s_client -connect localhost:31518. One of them only echoes what we send it, but the second one gives us a private key when we provide the password! All we need to do is copy the private key from the shell, exit the SSH session, create a local file on our computer (I called it bandit17.sshkey), paste our key into it, and login!

Oh wait…

ssh bad permissions

The ssh client chosses to ignores private key files which are too overly permissive. This is due to security concerns. We need to change the permissions to be only readable by us, or to 400, using chmod.

bandit 16 win

Level 17 -> Level 18

diff passwords.old passwords.new

Nothing to write up about, really :)

Level 18 -> Level 19

After logging in we get logged right out!

bashrc nonsense

This is because of a modified .bashrc file which prints “Bye Bye” and kills the shell. We can’t read the files from the previous user (bandit18) since we don’t have permissions to do so. And bash opens up automatically since it’s the login shell.

However, instead of running an interactive session and therefore opening up the login shell, we can run a command directly from ssh:

echo hello over ssh

So to win this stage, all we need to do is:

win bandit18

Level 19 -> Level 20

In this level we are presented with a suid binary. This is quite a difficult concept so let’s make sure we understand it. First off you need to understand Unix permissions. Luckily, @b0rk explains it in a very simple way:

unix permission by @b0rk

See that last panel? That’s the key for this stage. Let’s run ls -l and see what we get.

ls -l bandit 19

And let’s break it down according to what we’ve learned about permissions:

  • -rwsr-x--- This is divided into three parts:
    • rws means that the user can read, write and suid - execute and change the EUID during execution to the user as well. In case you missed it, EUID (which stands for Effective User ID) is what is actually checked when the Operating System checks a process for permissions.
    • r-x means that the group can read and execute the file.
    • --- means that everyone don’t have any access to this file.
  • bandit20 bandit19 - These are, in order, the user and the group.

Seems like we should have execution rights. Let’s run the file and see what we get!

run the suid

The SUID binary changed the EUID to bandit20, and then ran whichever command we told it to run. So let’s read the password file as bandit20.

win bandit19

Level 20 -> Level 21

This level combines a lot of our knowledge from previous stages. We need to set up a server which will listen on a port of our choosing and then use the SUID binary to connect to it. We can use nc -l -p 5656 (-l means listen and -p 5656 indicates which port we chose), like so:

Set up the server

Then, instead of transmitting “hello”, we will transmit the current password.

win bandit 20

Level 21 -> Level 22

In this level we learn about cron and the crontab files. So read about those here and then the level becomes quite easy.

The cronjob_bandit22 runs the /usr/bin/cronjob_bandit22.sh script every minute and after reboot as well. The script just saves the password in a temporary file and gives read permissions to everyone, so we read it and win!

crontab level

Level 22 and beyond

Well, we haven’t solved them yet. We’re going to sleep 😴 Be on the lookout for part 3!