PHP序列化和反序列化语法悬殊题目
官方文档中介绍PHP序列化和反序列化如下: (引荐学习:PHP视频教程)
所有php里面的值都可以使用函数serialize()来返回一个包括字节流的字符串来表示。unserialize()函数能够从新把字符串变回php本来的值。序列化一个对象将会留存对象的所有变量,但是不会留存对象的办法,只会留存类的名字。为了能够unserialize()一个对象,这个对象的类必需已经定义过。假如序列化类A的一个对象,将会返回一个跟类A相关,并且包括了对象所有变量值的字符串。
简便说序列化是对象转化字符串的历程,反序列化是字符串复原对象的历程。
环境
文章中所述内容使用环境如下:
PHP7.3.1、SDK VSCode C++和C
环境配置倡议参照 :《WINDOWS下用VSCODE调试PHP7源代码》
在网上公示参数反序列化施行流程已经非常具体,但是关于一些细节地方有一些不足,其中就包罗序列化和反序列化之间的语法差别问题
差别问题
序列化
我们通过编译PHP内核源码剖析,发明PHP序列化在默许状况下在对象转换中参加:{和}用来拼接成字符串。
[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, '}');
咱们来看上面这段代码,PHP会使用smart_str_appendl为序列化字符串前后拼接:{和},从var.c的第882行开端进入序列化逻辑。在第896行停止序列化字符串拼接,第952行和第995行,关于内嵌办法停止拼接。
反序列化
反序列化是将序列化的字符串,依照必然语律例则停止转化复原。
[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? */ }
通过内核代码能够看到第655行进入反序列化,反序列化是利用词法扫描,推断各项符号转换对应对象。能够看到反序列化中关于}停止了处置,处置中只是对计数器加一并没有其他操纵。
实际作用
反序列化语法的差别,关于平安防护设备推断反序列化发生很大的影响。在Snort中,有段规则如下:
alert tcp any any -> any [80,8080,443] (uricontent:".php"; pcre:"/\{\w:.+?\}/"; sid:1; msg:php_serialize;)
在攻击载荷中可以使用大多数字符代替{},从而致使规则失效。
总结
在红队攻击中可以利用PHP序列化和反序列化语法差别,从而到达绕过防护的目的。
在蓝队防备中倡议思考定义中所述不会留存对象的办法,只会留存类的名字。,拦截留存类的名字,乃至语法中雷同的字符比方冒号停止防备。
以上就是PHP序列化和反序列化语法差别问题的具体内容,更多请关注百分百源码网其它相关文章!