php的反序列化利用

一、简介

为了有效地存储或传递数据,同时不丢失其类型和结构,持久化对象,经常需要利用序列化和反序列化函数对数据进行处理。重点在于解决php对象传递和存储的问题。

1、序列化和反序列化

  • 序列化函数将各种类型的数据压缩为字符串,该字符串可以存储于任何地方。
  • 反序列化函数将可传输的包含字节流的字符串转换回原来的值。

2、php中常使用的序列化和反序列化函数

  • serialize()
  • unserialize()
  • json_encode()
  • json_decode()

二、序列化

当序列化对象时,PHP将试图在序列动作之前调用该对象的成员函数 __sleep() ,这就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象之前,将调用 __wakeup() 成员函数。

1、php序列化格式


序列化格式

2、例子

class test
{
    private $flag = 'Inactive';
    protected $test = "test";
    public $test1 = "test1";

    public function set_flag($flag)
    {
        $this->flag = $flag;
    }

    public function get_flag()
    {
        return $this->flag;
    }
}

$object = new test();
$object->set_flag('Active');
$data = serialize($object);
echo $data;
  • 输出:O:4:"test":3:{s:10:"testflag";s:6:"Active";s:7:"*test";s:4:"test";s:5:"test1";s:5:"test1";}
  • 说明:
    (1)O代表这是一个对象,对象名占4个字符,对象名是“test”,对象有3个属性。
    (2)s:10:"testflag";s:6:"Active";前面代表属性名,后面表示属性值。
    (3)PHP 的属性的访问权限问题:属性权限不同,对应的序列化表示也有区别。
  • public权限:序列化常规思路,例s:5:"test1";s:5:"test1";。
  • private权限:该权限是私有权限,也就是说只能 test类使用,在序列化的时候一定要在 private 属性前面加上自己的名字。在私有属性序列化的时候格式是%00类名%00属性名,例s:10:"testflag";s:6:"Active";。
  • protected权限:格式是%00%00属性名,例s:7:"test";s:4:"test";。
  • 在传入序列化字符串进行反序列化时需要注意补齐两个空字节。O:4:"test":1:{s:10:"%00test%00flag";s:6:"Active";}
  • 注意:序列化只序列化属性,不序列化方法。

三、反序列化

unserialize是反序列化函数。若被序列化的变量是一个对象,在重新构造对象之后,会自动调用__wakeup成员函数。

例子:


反序列化

四、反序列化漏洞利用

  • 在反序列化的时候一定要保证在当前的作用域环境下有该类存在。因为我们没有序列化方法,因此在反序列化以后我们如果想正常使用这个对象的话我们必须要依托于这个类要在当前作用域存在的条件。
  • 在反序列化攻击的时候也就是依托类属性进行攻击。因为没有序列化方法嘛,我们能控制的只有类的属性,因此类属性就是我们唯一的攻击入口,在我们的攻击流程中,我们就是要寻找合适的能被我们控制的属性,然后利用它本身的存在的方法,在基于属性被控制的情况下发动我们的发序列化攻击。

核心思想:寻找合适的能被控制的属性,利用它本身存在的方法发动攻击。

1、简介
反序列化漏洞的产生主要有以下两个原因:
(1)unserialize函数的参数可控。
(2)存在魔法函数。

2、魔法函数

__construct() //对象创建时触发
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发
__set_state()
__clone()
__debugInfo()

(1)__sleep()函数和__wakeup()函数

  • serialize()函数会检查类中是否存在__sleep函数。如果存在,该函数会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该函数未返回任何内容,则NULL被序列化,并产生一个E_NOTICE级别的错误。

  • __sleep()函数不能返回父类的私有成员的名字。这样做会产生一个E_NOTICE级别的错误。该函数可以用serializable接口来代替。

  • __sleep函数常用于提交未提交的数据或进行类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,则使用此功能比较好。

  • unserialize函数会检查是否存在__wakeup函数。如果存在,则会先调用__wakeup函数,预先准备对象需要的资源。

  • __wakeup函数经常用在反序列化操作中,例如,重新建立数据库连接或执行其他初始化操作。


    __sleep()函数和__wakeup()函数

绕过wakeup()方法:CVE-2016-7124漏洞,当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行。漏洞影响版本:PHP5 < 5.6.25 PHP7 < 7.0.10。

wakeup函数绕过

(2)__construct()函数和__destruct()函数

  • construct是构造函数(PHP5),具有构造函数的类会在每次创建新对象时先调用此方法,所以construct函数非常适合在使用对象之前做一些初始化工作。

  • destruct是析构函数(PHP5),析构函数会在对某个对象的所有引用都被删除或者对象被显式销毁时执行。

__construct()函数和__destruct()函数

(3)__toString()函数

  • __toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。

__toString()函数的触发条件:

  • (1)echo (obj) / print(obj) 打印时会触发
  • (2)反序列化对象与字符串连接时
  • (3)反序列化对象参与格式化字符串时
  • (4)反序列化对象与字符串进行==比较时(PHP进行==比较的时候会转换参数类型)
  • (5)反序列化对象参与格式化SQL语句,绑定参数时
  • (6)反序列化对象在经过php字符串函数,如 strlen()、addslashes()时
  • (7)在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用
  • (8)反序列化的对象作为 class_exists() 的参数的时候

五、session反序列化漏洞

  • PHP在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取 $_SESSION 数据,都会对数据进行序列化和反序列化。

六、POP链

POP 面向属性编程(Property-Oriented Programing) 常用于上层语言构造特定调用链的方法,与二进制利用中的面向返回编程(Return-Oriented Programing)的原理相似,都是从现有运行环境中寻找一系列的代码或者指令调用,然后根据需求构成一组连续的调用链,最终达到攻击者邪恶的目的。类似于PWN中的ROP,有时候反序列化一个对象时,由它调用的__wakeup()中又去调用了其他的对象,由此可以溯源而上,利用一次次的“gadget”找到漏洞点。

  • POP CHAIN:把魔术方法作为最开始的小组件,然后在魔术方法中调用其他函数(小组件),通过寻找相同名字的函数,再与类中的敏感函数和属性相关联,就是POP CHAIN 。此时类中所有的敏感属性都属于可控的。当unserialize()传入的参数可控,便可以通过反序列化漏洞控制POP CHAIN达到利用特定漏洞的效果。
一些有用的POP链中出现的方法:
- 命令执行:exec()、passthru()、popen()、system()
- 文件操作:file_put_contents()、file_get_contents()、unlink()

七、利用 phar:// 拓展 PHP 反序列化的攻击面

1、利用phar文件会以序列化的形式存储用户自定义的meta-data这一特性,拓展了php反序列化漏洞的攻击面。该方法在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。
2、利用条件

  • phar文件要能够上传到服务器端。
  • 如file_exists(),fopen(),file_get_contents(),file()等文件操作的函数要有可用的魔术方法作为"跳板"。
  • 文件操作函数的参数可控,且: / phar等特殊字符没有被过滤。

八、相关题目

1、http://web.jarvisoj.com:32768/index.php
2、ciscn2019 web1- JustSoso
3、https://code-breaking.com/puzzle/7/
4、工具
phpggc:收集了一些常见的PHP框架的通用反序列化的小工具https://github.com/ambionics/phpggc

参考:
1、https://xz.aliyun.com/t/3674
2、https://www.k0rz3n.com/2018/11/19/%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0%E5%B8%A6%E4%BD%A0%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/
3、https://chybeta.github.io/2017/06/17/%E6%B5%85%E8%B0%88php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/4、https://www.anquanke.com/post/id/864525、https://www.smi1e.top/php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%94%BB%E5%87%BB%E6%8B%93%E5%B1%95/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351