PHP審計之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

結果:

 [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這單個方法作為反序列化的入口點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM