代码审计---反序列化实例(Tpyecho typecho-1.1-15.5.12-beta)

 

第一次学习审这样的源码,主要参考两篇文章:

1、https://mochazz.github.io/2018/09/12/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1Day11%20-%20unserialize%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/

2、http://www.freebuf.com/column/161798.html

 

源码下载地址:https://github.com/typecho/typecho/archive/v1.1-15.5.12-beta.zip

漏洞发生在install.php页面

这次审计用的工具有:

1、sublime text3

2、Phpstrom

3、Phpstudy

4、Burpsuite

 

分析:

正常安装这个站点

漏洞点在install.php页面

这里可以看到,这里将cookie __typecho_config的值取进来,先base64解密,然后再进行反序列化

第一步就是先让代码运行到这里

看前面的限制:

 

输入finish=1可以绕过第一个if

第二个if判断是否有$_GET()$_POST()

当第一个绕过,第二个就过了,然后下面有一个判断Referer,修改一下Referer: 你的站点  就可以绕过

然后下面还有页面的一些限制

 

我们要进入的是最后一个判断,就是说要绕过前面两个

第一个判断,如果已经安装了的话,直接可以过

第二个判断,判断cookie是否有__typecho_config

那么输入__typecho_config=任何字符,就可以绕过

下面就到了反序列化函数了。

这里如果直接在burpsuite里面运行的话,会报错的,因为后面的有一些代码运行的出错,因为我们这里是随便输入的,后面的一些函数有可能执行不了,如果要判断是否运行正确了,可以用phpstrom单步调试一下

 

跟着代码往下走:

 

代码这里新建一个对象

可以看到这里是把 $config['adapter'] 当作字符串来用的,那么如果这里的 $config['adapter'] 不是一个字符串,而是一个对象,那么就会调用这个对象里面的__toString()函数,查一下代码中,哪个class 里面 存在 __toString()

每一个都看一下

这个返回一个序列化,没有可以继续利用的

下一个

 

这个是拼接数据库操作的,也没有可以利用的

下一个

 

在这里,第291行,$item['author']->screenName 这里可以利用,因为反序列化就是利用不同的魔术方法,如果这里的$item['author']是一个对象,如果这个对象里面没有screenName这个变量,那么就会去执行这个对象里面的__get()方法,继续查一下哪个class里面有__get()方法

 

查一下这些方法

 

直接返回,不能利用

 

这个也不能利用

这个也不行

 

这个也不行

 

这个也不行

下面看到Request.php页面,这个是可以利用的

 

分析一下这些方法

先是 __get()方法 ----get() 方法 ----_applyFilter()方法

__get()方法直接调用get()方法

get()方法里面,先判断是否存在$this->_params[$key],如果存在那么 $value = $this->_params[$key];

然后判断$value 值是否是数组,且长度是否大于0 ,如果不是数组,且大于0,返回值就等于 $value

进入到 _applyFilter()方法

可以看到这个方法里面,有两个可以执行方法的函数

array_map() 和 call_user_func() 具体使用方法查百度或google

看一下进入两个判断的限制

先判断是否有 $this->_filter

然后做foreach() 也就是说 $this->_filter要是一个数组

然后再判断$value是否是数组,前面的get() 里面判断了 $value 不是一个数组,那么这里就进入的是 call_user_func()

但是这个函数怎样执行呢

函数的用法就是

call_user_func‘函数名’,’参数’)

例如,如果执行call_user_func(‘phpinfo’,’-1’)  就会执行phpinfo() ,那个-1不用管,因为phpinfo()是不用参数的

那么如果 call_user_func(‘assert’,’file_put_contents("test.txt","Hello World")’)

就会执行文件的写入,也就是可以写shell

 

理清了利用的思路,下面就是编写exp了,建议可以边理思路,边写 exp,当然如果很熟悉php 可以不用边理边写

 

思路:

install.php 绕过限制,输入cookie ---Db.php 拼接的时候,因为对象被当作字符串使用,执行__toString() ------__toString() 所在的classTypecho_Feed ,所以要构造一个 class Typecho_Feed -----》 执行__get() ,__get()方法在对象 Typecho_Request 里面,所以要构造一个 class Typecho_Request

 

编写exp ,不要放在和站点同个服务器,不然会调用到编写expclass,所以我这里用的是在线的编译器 http://www.dooccn.com/php/

代码没有办法一行一行解析,如果有不懂的,再交流一下吧

 

发送过去会报错,但是这个是因为程序运行到后面,代码的出错,不影响利用的流程。

访问一下 http://127.0.0.1:8089/test.txt

 

已经写入了。

 

 

 

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/nienie/p/9785018.html