PHP反序列化基础知识

魔术方法:

注:魔术方法只有在类中被定义以后才可以触发

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法,这些都是 PHP 内置的方法。
__construct() 当一个对象创建时被调用,
__destruct() 当一个对象销毁时被调用,
__wakeup() 使用 unserialize 时触发
__sleep() 使用 serialize 时触发
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用 isset()或 empty()触发
__unset() 在不可访问的属性上使用 unset()时触发
__toString() 把类当作字符串使用时触发,返回值需要为字符串
__invoke() 当脚本尝试将对象调用为函数时触发

一、序列化基础概念

1.什么是序列化,为什么要序列化

  PHP文件执行结束以后会将创建的对象自动销毁,对象序列化以后可以将对象存储起来方便下次的直接使用。

2.PHP序列化和反序列化函数

  serialize()   将对象转化为字符串

  unserialize() 反过来

3.示例

4.解释说明序列化后的具体内容

O:4:"Test":3:{s:7:"Testa";s:7:"private";s:1:"b";s:6:"public";s:4:"*c";s:9:"protected";}

第一部分:O:4:"Test":3:

O    表示一个对象 object

4   对象名称的长度为4

Test 对象的名称

3   对象有3个属性(变量)

第二部分:s:7:" Test a";s:7:"private";(这里不是空格而是空字符即十六进制\x00,不显示,我们需要在16进制编辑器或者bp中修改)

s:7:"Testa";s:7:"private";

s 变量名字符串string

7 变量名的长度为7  \x00Test\x00a

s 变量值字符串string

7 变量值的长度

private 变量值的内容

第三部分:s:1:"b";s:6:"public";

s:1:"b";s:6:"public";
很基础没有什么特别的需要描述

第四部分:s:4:" * c";s:9:"protected";(这里不是空格而是空字符即十六进制\x00,不显示,我们需要在16进制编辑器或者bp中修改

s:4:"*c";s:9:"protected";
4 变量名的长度为4  \x00*\x00c

5.总结

序列化就是把对象转化为字符串从而便于存储和传输

二、反序列化

 注:一定要注意空格,也就是说注意各个字符串之间对应的描述。

结果如下

三、反序列化漏洞原理

  当用户的请求在传给反序列化函数 unserialize()之前没有被正确的过滤时就会产生漏洞。因为 PHP允许对象序列化,攻击者就可以提交特定的序列化的字符串给一个具有该漏洞的 unserialize 函数,最终导致一个在该应用范围内的任意 PHP 对象注入。
前提:
  1. unserialize 参数用户可控
  2. 参数被传递到方法中被执行,并且方法中使用了危险函数。(php 代码执行函数、文件读取函数、文件写入函数等等)。
 
 
 演示:这里一定注意理解好构造的序列化对象代码包括各种细节

结果如下图 浅提一下这里没有加php代码的结尾分号注意自己去理解上面说的代码

 四、经典ctf反序列化题目

 

 解决如下图

 我们这里的payload注意将变量的数量从1改成2就可以绕过__wakeup()函数,破坏了代码逻辑的执行顺序从而达到绕过的目的;我们也可以再加真实属性的个数,这样也可以绕过__wakeup函数;将小写的s改为大写的S后就可以解析二进制了我们这里的\00就是二进制的空格。(还是改为%00吧因为后来我又测试了一遍没成功。)

posted @ 2022-09-25 16:06  hithub  阅读(87)  评论(0编辑  收藏  举报