小白学源码审计-6-PHP反序列化漏洞

原创 时间 2017-08-30  慕小白 神月资讯

许久不见,这次带来的是PHP反序列化漏洞的相关介绍。本文首先介绍一些基础原理,接着简单讲解相关漏洞的挖掘思路与防护手段。

0x01前言

许久不见,这次带来的是PHP反序列化漏洞的相关介绍。本文首先介绍一些基础原理,接着简单讲解相关漏洞的挖掘思路与防护手段。

0x02序列化与反序列化

序列化是指把对象转换为字符串的过程,便于保存在内存、文件、数据库中,PHP中使用serialize函数进行序列化。

微信图片_20170901111306.jpg

以上代码运行后会显示该段字符:

微信图片_20170901111319.jpg

O:1:说明是一个对象。

”a”:1说明对象a中有一个元素。

s:2:"a1";说明这是一个2个字符的字符串。

反序列化为序列化的逆过程,将字符串恢复成对象,PHP中使用unserialize函数完成反序列化的操作。

需要注意的是unserialize函数只能反序列化在当前程序上下文中已经被定义过的类,或者autoLoad自动加载机制可加载的类。

反序列化对象允许控制所有属性:publicprotectedprivate

微信图片_20170901111324.jpg

序列化与反序列化均为正常功能,其存在是合理的,但如果反序列化时,传入反序列化函数的参数用户可控则可能导致一些安全问题。

0x03魔术方法

PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),相关方法在某些场景中会被自动触发。魔术方法包括以下:

__construct __destruct  __call, __callStatic__get__set__isset__unset__sleep__wakeup__toString__set_state__clone__autoload

与反序列化紧密相关的魔术方法有两个:

__wakeup():执行unserialize()时,首先会调用这个函数。

__destruct():类的析构函数,对象结束其生命周期,会调用该函数。

在反序列化过程必然会调用以上两个方法。

简单的例子:

微信图片_20170901111328.jpg

访问该PHP文件,从打印的参数可以知道,__wakeup方法与__destruct方法在反序列化过程会被调用。

微信图片_20170901111331.jpg

0x04漏洞原理

从上两节可以知道,unserialize会调用反序列化对象中的__wakeup方法与__destruct方法,那么只要符合以下条件,就会导致安全风险。

  1. unserialize参数用户可控,即程序没有对反序列化的值进行有效的限制,导致反序列化的对象可被用户控制。

  2. 存在可被恶意利用的类,类中定义了可利用的__wakeup方法或者__destruct方法,如__destruct中使用了assert函数,且参数用户可控。

  3. 对象可被反序列化,即在调用unserialize方法时,当前程序上下文中相应类被定义,或者类可被autoLoad自动加载机制加载。

依据上述3个条件,编写一段存在漏洞的代码方便理解。

微信图片_20170901111334.jpg

a已经在程序上下文中定义,并且其__destruct方法中使用了危险函数assert,传入assert的参数为类属性command,并且反序列化的参数用户完全可控。(该代码仅为展示编写,现实中几乎不会存在)

那么我们向参数t传入【O:1:"a":1:{s:7:"command";s:10:"phpinfo();";}】即可执行phpinfo()

当然如果没有魔术方法,其实也是可能存在风险的,比如以下这段代码,程序员认为反序列化后的对象是normal类,其中action方法是安全的,因此在反序列化后就直接调用action方法,但是如果其还定义了另外一个evil类,存在与normal类同名action方法(危险),即会导致问题。

微信图片_20170901111346.jpg

<<上一篇下一篇>>