popchain与对应poc的构造分析

本文首发于:https://mp.weixin.qq.com/s?__biz=MjM5MTYxNjQxOA==&mid=2652850238&idx=1&sn=6f22d8ab7af687993330a2a1774a5579&chksm=bd5934f38a2ebde507c7964e5a0dcd4775dec3f62162a462d95814132a8cf546a9df1daa51e5&scene=0&xtrack=1#rd

1.切入漏洞点

       某应用使用了版本为6.0.2guzzlehttp/guzzle代码库,而且在其代码段中存在反序列化函数unserialize(),而且其入口参数为咱们能够控制的参数,那么接下来咱们就须要在其内部寻找咱们能够利用的类而且寻找能够利用的反序列时将会触发的__destruct()函数和__wakeup()函数,而后再在这两类方法中找可能存在漏洞的点,咱们能够在sublime中使用ctrl+shift+f键来在指定的文件夹下来查找咱们指定的函数,以下图为查找的效果php

 

2.构造pop

       咱们注意到vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php中存在__destruct()函数,而且咱们猜想filename属于文件型参数,可能与文件操做相关,所以咱们即可以定位到FileCookieJar.php文件中进行审计html

 

 

              函数体中存在save方法,所以咱们继续跟进到save方法shell

 

       咱们能够看到save方法中存在file_put_contents()函数,咱们猜想是否是能够在此进行写shell,其中入口参数$filename为类FileCookieJar的私有成员变量,是咱们能够控制的,$json变量来自$cookie变量,而又由于$cookie变量调用的getExpires()函数和getDiscard()函数和toArray()函数均是在SetCookie这个类中进行定义的,因此$cookie变量确定是SetCookie类实例化后的对象,从而来调用类中的方法。而且此时咱们须要知足json

       1.$cookie>getExpires() 返回Ture数组

       2.$cookie>getDiscard() 返回Falsecookie

       接下来咱们跟进到SetCookie.php中观察类SetCookie是如何定义的,composer

 


其中在SetCookie类中的成员变量里定义了私有静态成员变量$defaults和私有成员变量$datacurl

函数

 

       而且在其构造方法中$defaults的值将被$data数组中的值进行替换,而且将替换的结果赋值给$data变量。工具

       其中getExpires()函数和getDiscard()toArray()函数的定义以下所示:

 

 

 

 

       从上面三个函数的定义中能够看到,上面两个函数返回$data变量的两个键值,下面的函数直接返回$data变量。那么咱们可让这上面两个键值知足if条件,经过咱们实例化SetCookie类并传给其一个$data数组便可在其构造方法中完成赋值操做。

 

 


       到这里,假设咱们已经进入第一个箭头所指示的if条件语句中,那么此时将把$cookie对象所调用的toArray()函数的返回值(也就是咱们上面所说的SetCookie类中所定义的$data变量的值)赋给$json变量,接下来就会将$json变量的值写入变量$filename所对应的路径中,到此pop链已经完成。

3.相应poc构造

       最后,咱们在本地测试咱们以上的思路以及构造的pop链是否正确,首先编辑composer.json文件并在其中包含咱们所测试的对应版本的代码库

 


       接下来在composer的同级目录中执行

       1.curl -sS https://getcomposer.org/installer | php  //安装composer

       2.php composer.phar install                    //依赖代码库的安装

       简单说下composercomposer PHP 的一个依赖管理工具。它容许咱们声明项目所依赖的代码库,而且会在咱们的的项目中安装所依赖的代码库。composer.json中定义的require键值表明的含义是咱们将要开发的应用,依赖于guzzlehttp6.0.2版本,对于库的自动加载信息,composer 生成了一个 vendor/autoload.php 文件,咱们能够经过引入这个文件,从而实现开发中所须要的类的自动加载

 


       接下来就能够开始构造咱们的poc了,由于要用到上面说的类,因此咱们直接引入对应目录下的autoload.php就能够,这里的两条use语句只是使用了命名空间,具体的加载类交给咱们的autoload.php来完成,

 


       接着咱们就能够来构造咱们最终想要利用的file_put_contents()函数的文件路径名和文件内容,首先进行分析

 

 



       由于文件路径名$filename参数是类FileCookieJar的私有成员变量,而且在其构造函数中将直接将入口参数赋值给了$filename,并在其析构函数中调用了$filename的值(也就是在反序列化时将会调用$filename的值),所以咱们经过实例化FileCookieJar的匿名对象,并将想要写入的路径名做为其入口参数,就能够完成对$filename的赋值。又由于save方法要用到$cookie变量的值,而且$cookie变量的值必须由类SetCookie的实例化后的对象来进行赋值操做,而FileCookieJar的父类是CookieJar,而且在其中存在setCookie()方法,其入口参数为类SetCookie的实例化的对象,所以咱们成功地找到了为$Cookie变量赋值的方法,就是经过类FileCookieJar的实例化对象来调用父类中所定义的setCookie()方法,并将其入口参数值设置为类SetCookie的匿名实例化对象,从而实现$cookie变量的赋值。

       接下来咱们就要构造$cookie变量的数据了,首先咱们须要了解setCookie方法,它的入口参数为实例化的类SetCookie的匿名对象,其在函数中调用了validate函数对$cookie变量进行检测,而且定义了设置二次设置$cookie时的判断操做,这里咱们构造poc时只须要调用一次setCookie()函数,因此不会进入foreach循环

 


              也就是咱们的目标只有一个,那就是是必须使validate()函数返回True

 


 


 


 


       validate()函数要求咱们必须知足如下三个条件才可以返回true

1.$data[‘Name’]变量非空,而且不能为数字,而且必须为所规定的字符

2.$data[‘Value’]变量非空,而且不能为数字

3.$data[‘Domain’]变量非空,而且不能为数字

而且结合又由于$data[‘Expires’]不能为null,所以咱们能够肯定咱们必须须要设置的$data的键名为以上四个,那么接下来咱们就能够继续写咱们的poc了,咱们在实例化类FileCookieJar时将咱们想要写入shell的路径名做为入口参数传递进去,而后将php一句话写到$data变量的Name,Value,Domain中的任何一个值中,接着经过让类对象$tr1ple调用setCookie(),并将其入口参数设置为类SetCookie的匿名实例化(其入口参数为$data),就能够完成对$cookie变量的赋值,由于$cookie值最终会被传递给$json变量并通过json_encode()函数编码之后直接写入到咱们指定的路径中。

 


4.测试结果

       咱们的poc文件名为poc.php,经过执行php poc.php将会生成exp文件,其中为咱们序列化之后的exp数据


 


       接下来咱们能够反序列化exp中包含的数据来测试此exp可否执行成功

 

       经过执行结果咱们能够判断出已经成功反序列数据并写入shell了,说明咱们以前分析的思路和测试过程是正确的。

相关文章
相关标签/搜索