前置知识
序列化:关键函数serialize():将PHP中创建的对象,变成一个字符串。
反序列化:关键函数unserialize():将经过序列化的字符串转换回PHP值
为什么会产生反序列化漏洞?
PHP反序列化漏洞又称PHP对象注入,是因为程序对输入数据处理不当导致的。需要具备反序列化漏洞的前提:必须有unserailize()函数;unserailize()函数的参数必须可控(为了成功达到控制你输入的参数所实现的功能,可能需要绕过一些魔法函数)。
魔术方法
_call方法
如何调用该方法?
当调用一个没有在类中声明的方法时,可以调用__call()方法代替声明一个方法。接受方法名和数组作为参数。
简单来说:调用了一个没有声明的方法,自动触发_call方法
简单代码示例:
<?php
class test{
//魔术方法__call
/*
$method 获得方法名
$arg 获得方法的参数集合
*/
public function __call($method,$arg){
echo '你想调用我不存在的方法',$method,'方法<br/>';
echo '还传了一个参数<br/>';
echo print_r($arg),'<br/>';
}
$list=new test();
$list->say(1,2,3);
?>
/*
输出结果:
你想调用我不存在的方法say方法
还传了一个参数
Array
(
[0] => 1
[1] => 2
[2] => 3
)
1
*/
__invoke
如何调用该方法?
当一个对象类中存在__invoke魔术方法,这个对象类被当作函数进行调用时,就会触发_invoke魔术方法
简单来说:
当你以调用函数的方式调用一个对象时会触发
简单代码示例:
<?php
Class studyphp {
public function __invoke($arg) {
echo "invoke被调用咯: " . $arg;
}
}
$a = new studyphp();
$a("我是invoke被调用咯");
?>
/*可以手动输出去看看*/
/* 输出结果:
invoke被调用咯: 我是invoke被调用咯
*/
我自己基础比较差,当时没理解什么叫以调用函数的方式调用对象
这么来说 函数是这么调用的,举个简单的例子
下面演示了如何调用一个名为 myFunction 的函数,并传递 1 和 2 两个参数:
$result = myFunction(1, 2);
如果还是不理解 就这么说,对象是->这样调用的 而函数是类似这样$a();
调用的
_set
如何调用该方法?
__set() 魔术方法是当给一个对象不存在的变量赋值时就会被触发
简单来说: 上面的说法就够简单了吧 :stuck_out_tongue:
简单代码示例:
拿我做的一道题举例子
这个里边 fun并没有被定义 却被复制了 所以会跳转到_set魔术方法
(自己的拙见,跟着佬的wp反推的,不知道对不对,如果不对的话还请谅解斧正)
__toString
如何调用该方法?
_ toString当我们将一个对象打印为字符串或使用 echo 函数输出对象时,会自动调用__toString方法
也就是 : 在对象当做字符串的时候会被调用
简单来说:对象当做字符串的时候会被调用,就比如 :直接echo对象的的就会自动调用该方法
<?
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function __toString() {
return 'This person\'s name is ' . $this->name;
}
}
$person = new Person('John');
echo $person;
?>
__unset
对不可访问或不存在的属性进行unset时被调用
__callStatic
调用不可访问或不存在的静态方法时被调用
__clone
进行对象clone时被调用,用来调整对象的克隆行为
__constuct
构建对象的时被调用;
__debuginfo
当调用var_dump()打印对象时被调用(当你不想打印所有属性)适用于PHP5.6版本
__destruct
明确销毁对象或脚本结束时被调用;
__get
读取不可访问或不存在属性时被调用
__sleep
当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用
__set_state
当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。
__isset
对不可访问或不存在的属性调用isset()或empty()时被调用