PHP反序列化


前置知识

序列化:关键函数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 的函数,并传递 12 两个参数:

$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()时被调用


文章作者: Rmy4x
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Rmy4x !
  目录