您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“PHP序列化和反序列化語(yǔ)法的差異”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
官方文檔中介紹PHP序列化和反序列化如下:
所有php里面的值都可以使用函數(shù)serialize()來(lái)返回一個(gè)包含字節(jié)流的字符串來(lái)表示。unserialize()函數(shù)能夠重新把字符串變回php原來(lái)的值。 序列化一個(gè)對(duì)象將會(huì)保存對(duì)象的所有變量,但是不會(huì)保存對(duì)象的方法,只會(huì)保存類(lèi)的名字。 為了能夠unserialize()一個(gè)對(duì)象,這個(gè)對(duì)象的類(lèi)必須已經(jīng)定義過(guò)。如果序列化類(lèi)A的一個(gè)對(duì)象,將會(huì)返回一個(gè)跟類(lèi)A相關(guān),而且包含了對(duì)象所有變量值的字符串。
簡(jiǎn)單說(shuō)序列化是對(duì)象轉(zhuǎn)化字符串的過(guò)程,反序列化是字符串還原對(duì)象的過(guò)程。
文章中所述內(nèi)容使用環(huán)境如下:
PHP7.3.1、SDK VSCode C++和C
環(huán)境配置建議參考:《WINDOWS下用VSCODE調(diào)試PHP7源代碼》https://www.jianshu.com/p/29bc0443***6(作者經(jīng)過(guò)幾小時(shí)嘗試后找到最全的版本)
在網(wǎng)上公開(kāi)參數(shù)反序列化執(zhí)行流程已經(jīng)非常詳細(xì),但是對(duì)于一些細(xì)節(jié)地方有一些不足,其中就包括序列化和反序列化之間的語(yǔ)法差異問(wèn)題
我們通過(guò)編譯PHP內(nèi)核源碼分析,發(fā)現(xiàn)PHP序列化在默認(rèn)情況下在對(duì)象轉(zhuǎn)換中加入:{和}用來(lái)拼接成字符串。
[var.c] Line:882 static void php_var_serialize_intern() Line:896 if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS) { smart_str_appendl(buf, "C:", 2); smart_str_append_unsigned(buf, ZSTR_LEN(Z_OBJCE_P(struc)->name)); smart_str_appendl(buf, ":\"", 2); smart_str_append(buf, Z_OBJCE_P(struc)->name); smart_str_appendl(buf, "\":", 2); smart_str_append_unsigned(buf, serialized_length); smart_str_appendl(buf, ":{", 2); smart_str_appendl(buf, (char *) serialized_data, serialized_length); smart_str_appendc(buf, '}'); } Line:952 smart_str_appendl(buf, ":{", 2); Line:995 smart_str_appendc(buf, '}');
咱們來(lái)看上面這段代碼,PHP會(huì)使用smart_str_appendl為序列化字符串前后拼接:{和},從var.c的第882行開(kāi)始進(jìn)入序列化邏輯。在第896行進(jìn)行序列化字符串拼接,第952行和第995行,對(duì)于內(nèi)嵌方法進(jìn)行拼接。
反序列化是將序列化的字符串,按照一定語(yǔ)法規(guī)則進(jìn)行轉(zhuǎn)化還原。
[var_unserialize.c] Line:655 static int php_var_unserialize_internal() Line:674 { YYCTYPE yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); yych = *YYCURSOR; switch (yych) { case 'C': case 'O': goto yy4; case 'N': goto yy5; case 'R': goto yy6; case 'S': goto yy7; case 'a': goto yy8; case 'b': goto yy9; case 'd': goto yy10; case 'i': goto yy11; case 'o': goto yy12; case 'r': goto yy13; case 's': goto yy14; case '}': goto yy15; default: goto yy2; } Line:776 yy15: ++YYCURSOR; { /* this is the case where we have less data than planned */ php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ }
通過(guò)內(nèi)核代碼能夠看到第655行進(jìn)入反序列化,反序列化是利用詞法掃描,判斷各項(xiàng)符號(hào)轉(zhuǎn)換對(duì)應(yīng)對(duì)象。能夠看到反序列化中對(duì)于}進(jìn)行了處理,處理中只是對(duì)計(jì)數(shù)器加一并沒(méi)有其他操作。
反序列化語(yǔ)法的差異,對(duì)于安全防護(hù)設(shè)備判斷反序列化產(chǎn)生很大的影響。在Snort中,有段規(guī)則如下:
alert tcp any any -> any [80,8080,443] (uricontent:".php"; pcre:"/\{\w:.+?\}/"; sid:1; msg:php_serialize;)
在攻擊載荷中可以使用大多數(shù)字符代替{},從而導(dǎo)致規(guī)則失效。
“PHP序列化和反序列化語(yǔ)法的差異”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。