php反序列化

PHP反序列化链

PoP链的核心,就是魔术方法。而php的魔术方法中涉及到反序列化的大致有以下几种:

__destruct: 析构函数,会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。一般来说,也是Pop链的入口。
__toString: 类对象遇到字符串操作时触发。
__wakeup:   类实例反序列化时触发。
__call:    当调用了类对象中不存在或者不可访问的方法时触发。
__callStatic: 当调用了类对象中不可访问的静态方法时触发。
__get:     当获取了类对象中不可访问的属性时触发。    
__set:     当试图向类对象中不可访问的属性赋值时触发。
__invoke:   当对象调用为函数时触发

通俗来讲,我们可以把__destruct当作挖掘反序列化链的入口,因为__wakeup一般内容为反序列化的限制。

__destruct开始,我们探讨,在不同的情况下我们分别会如何寻找调用链?

__call

function __destruct(){
    $this->a();
}

我们可以直接跟下去看a方法的内容,如果当前类不存在a方法,则会优先查找父类的a方法。如果父类也不存在a方法(或是不可访问),那么就会触发当前类的__call魔术方法。

$this->a() ==> 当前类a方法 ==> 父类a方法 ==> 当前类__call方法 ==> 父类__call方法

值得注意的是,如果触发__call方法,那么a会作为__call的方法的第一个参数,而参数列表会作为__call的方法第二个参数。

而当代码出现

function __destruct(){
    $this->a->b();
}

此时,我们便不用纠结于$this->a是代表什么类了,我们可以调用任意类的b方法。换言之,我们也可以调用任意没有b方法的类对象的__call方法。

 $this->a->b() ==> 任意类的b方法 ==> 任意类的`__call`方法

__get__set

当代码出现

function __destruct(){
    echo $this->a;
}

这时echo会优先访问当前类的a变量,然后寻找父类的a变量,如果不存在该类变量或者不可访问时,则会调用对应的__get方法

$this->a ==> 当前类a变量 ==> 父类a变量 ==> 当前类__get方法 ==> 父类__get方法

同样,如果调用$this->a->b,我们就有可能触发任意类的__get方法。

而当代码出现

function __destruct(){
    $this->a = 1;
}

如果当前类不存在a变量时,则会触发__set方法

__toString

__toSring是一个很特别的魔术方法,当类对象遇到字符串操作时触发。

他一般常见于这种代码中

function __destruct(){
    echo $this->a;
}

当我们控制$this->a时,我们就可以触发任意类的__toSring方法。

echo $this->a ==> 任意类的__toSring

其他方法

其他方法主要包括__wakeup__invoke,这两种方法比较特殊,在反序列化链中出现的概率比较小。

由于__wakeup是在反序列化时执行,所以一般来说,开发者会倾向于在wakeup函数中加入过滤部分,以减少反序列化漏洞的危害。

__invoke触发条件是当尝试以调用函数的方式调用一个对象时。但可惜的是,如果你试图调用一个方法时,会优先执行__call逻辑,而不是invoke。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇