PHP审计之POP链挖掘

PHP审计之POP链挖掘前言续上文中的php反序列化,继续来看,这个POP的挖掘思路。在其中一直构思基于AST去自动化挖掘POP链,迫于开发能力有限。没有进展,随后找到了一个别的师傅已经实现好的项

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

PHP审计之POP链挖掘

前言

续上文中的php反序列化,继续来看,这个POP的挖掘思路。在其中一直构思基于AST去自动化挖掘POP链,迫于开发能力有限。没有进展,随后找到了一个别的师傅已经实现好的项目。

魔术方法

__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发,file_exists()判断也会触发
__invoke() //当脚本尝试将对象调用为函数时触发

__call__callstatic

现实情况下__call的利用居多,该魔术方法触发的条件是在对象上下文中调用不可访问的方法时触发。

调用流程如下:

$this->a() ==> 当前类a方法 ==> 父类a方法 ==> 当前类__call方法 ==> 父类__call方法

如果触发__call方法,那么a,即方法名,会作为__call的方法的第一个参数,而参数列表会作为__call的方法第二个参数。

来看到代码

function __destruct(){
    $this->a->b();
}

这里有2个利用路径,一个是$this->a中构造一个存在方法的实例化类,另一种方式是找一个不存在b方法并且存在__call方法的类,当b不存在时,即自动调用__call

__callstatic方法只有在调用到静态方法的时候才能触发

__get__set

不存在该类变量或者不可访问时,则会调用对应的__get方法

$this->a ==> 当前类a变量 ==> 父类a变量 ==> 当前类__get方法 ==> 父类__get方法

__get代码案例

function __destruct(){
    echo $this->a;
}

调用不存在变量a,即会自动触发__get方法,

数据写入不可访问的变量或不存在的变量即调用__set

function __destruct(){
    $this->a = 1;
}

__toString

把类当作字符串使用时触发

$this->_adapterName = $adapterName;
$adapterName = 'xxx' . $adapterName;

POP链挖掘

此前构思的自动化挖掘POP链的功能已经被其他师傅实现了,在此就不班门弄斧了,直接拿现成的来用。
按照个人理解反序列化入口点一般为__wakeup__destruct__construct
思路其实就是寻找__destruct方法,作为入口点,然后寻找一个回调函数作为末端。而中间需要寻找各种中间链,将其串联起来。串联的方法基本上就是一些魔术方法和一些自定义的方法。

项目地址:https://github.com/LoRexxar/Kunlun-M

cp Kunlun_M/settings.py.bak Kunlun_M/settings.py

python kunlun.py init initialize

python kunlun.py config load

python kunlun.py plugin php_unserialize_chain_tools -t C:\kyxscms-1.2.7

PHP审计之POP链挖掘

结果:

 [20:28:51] [PhpUnSerChain] New Source __destruct() in thinkphp#library#think#Process_php.Class-Process
 [20:28:51] thinkphp#library#think#Process_php.Class-Process
 newMethod                        Method-__destruct()
 [20:28:51] thinkphp#library#think#Process_php.Class-Process.Method-__destruct
 MethodCall                       Variable-$this->stop()
 [20:28:51] thinkphp#library#think#Process_php.Class-Process.Method-stop
 MethodCall                       Variable-$this->updateStatus('Constant-false',)
 [20:28:51] thinkphp#library#think#Process_php.Class-Process.Method-updateStatus
 MethodCall                       Variable-$this->readPipes('Variable-$blocking', '\ === Constant-DIRECTORY_SEPARATOR ? 627')
 [20:28:51] thinkphp#library#think#Process_php.Class-Process.Method-readPipes
 MethodCall                       Variable-$this->processPipes->readAndWrite('Variable-$blocking', 'Variable-$close')
 [20:28:51] thinkphp#library#think#console#Output_php.Class-Output
 newMethod                        Method-__call('$method', '$args')
 [20:28:51] thinkphp#library#think#console#Output_php.Class-Output.Method-__call.If
 FunctionCall                     call_user_func_array("Array-['Variable-$this', 'block']", 'Variable-$args')
 [20:28:51] [PhpUnSerChain] UnSerChain is available.

这其实利用链就清晰了

Process->__destruct ==>Process->stop ==>Process->updateStatus ==> Process->readPipes ==> Output->readAndWrite ==> Output->__call==> call_user_func_array()

内容补充

查看一下这三个方法的调用

<?php

class User{

    const SITE = 'uusama';



    public $username;

    public $nickname;

    private $password;

    private $id;



    public function __construct($username, $nickname, $password)

    {

        $this->username = $username;

        $this->nickname = $nickname;



    }



    // 定义反序列化后调用的方法

    public function __wakeup()

    {

        $this->password = '1234';

    }
    public function __destruct(){
        $this->id = '123';
    }

}
$user = new User('uusama', 'uu', '12345');
$ser= serialize($user);
var_dump(unserialize($ser));

结果:

object(User)[2]
  public 'username' => string 'uusama' (length=6)
  public 'nickname' => string 'uu' (length=2)
  private 'password' => string '1234' (length=4)
  private 'id' => null

在反序列化中一般开发可能会在__wakeup中做一些过滤。

参考

浅析 PHP 反序列化漏洞的利用与审计

如何自动化挖掘php反序列化链 – phpunserializechain诞生记

结尾

但该工具并没有达到我个人的预期,因为该工具中只是使用__destruct这单个方法作为反序列化的入口点。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119834.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 网站友链html代码_html底部友情链接代码

    网站友链html代码_html底部友情链接代码使用PHPcms建站的时候会经常遇到,添加友情链接。那么如何在phpcms的网站里面添加友情链接呢{pc:linkaction=”type_list”typeid=”0″siteid=”1″linktype=”1″order=”listorderDESC”num=”8″return=”pic_link”}{loop$pic_link$v}{$v[name]}{/loop}{/…

    2022年10月24日
    0
  • 2021 goland mac 激活码-激活码分享[通俗易懂]

    (2021 goland mac 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月20日
    592
  • leavecriticalsection报错_sequence的用法

    leavecriticalsection报错_sequence的用法线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法注:使用结构CRITICAL_SECTION需加入头文件#include“afxmt.h”定义一个全局的锁CRITICAL_SECTION的实例和一个静态全局变量CRITICAL_SECTIONcs;//可以理解为锁定一个资源statici

    2022年9月20日
    0
  • 基于单片机的功放protues_基于Proteus的音频放大器电路设计与仿真详解.doc[通俗易懂]

    基于单片机的功放protues_基于Proteus的音频放大器电路设计与仿真详解.doc[通俗易懂]毕业论文学生姓名尹有友学号171107078学院物理与电子电气工程学院专业电子信息工程题目基于Proteus的音频放大电路设计与仿真指导教师付浩副教授/学士2015年5月论文原创性声明内容本人郑重声明:本论文是我个人在导师指导下进行的研究工作及取得的研究成果。本论文除引文外所有实验、数据和有关材料均是真实的。尽我所知,除了文中特别加以标注和致谢的地方外…

    2022年6月6日
    34
  • eclipse的svn使用教程_eclipse svn插件安装

    eclipse的svn使用教程_eclipse svn插件安装eclipse中使用svn:在eclipse中安装svn插件a.离线方式下载eclipse_svn_site.zip解压到eclipse\dropins(eclipse插件目录)b.在线方式help->EclipseMarketplace搜:subversion使用:项目组长:发布项目预处理:右键要发布的项目-team-shareproject-svn-。。。输入…

    2022年9月26日
    0
  • poetry下载_烘手器安装

    poetry下载_烘手器安装介绍Poetry是Python中的依赖管理和打包工具,当然它也可以配置虚拟环境。它允许您声明项目所依赖的库,并为您管理(安装/更新)它们。之前一直使用virtualenvwrapper管理虚拟

    2022年7月30日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号