zoukankan      html  css  js  c++  java
  • 代码审计---反序列化实例(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

     

    已经写入了。

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
  • 原文地址:https://www.cnblogs.com/nienie/p/9785018.html
Copyright © 2011-2022 走看看