PHP string序列化与反序列化语法解析不一致带来的安全隐患

admin 2021年4月3日19:27:30评论75 views字数 3616阅读12分3秒阅读模式

PHP string序列化与反序列化语法解析不一致带来的安全隐患

原文地址:http://www.80vul.com/pch/pch-010.txt

author: ryat#www.wolvez.org

team:http://www.80vul.com

date:2012-11-19

不久前 IPB 爆出了一个 unserialize() 漏洞[1],漏洞本身没有什么特别的,但 IPB 官方发布的 patch 却很有意思[2],很快 Stefan Esser 在其 twitter 上给出了 bypass 的方法[3]。随后 IPB 官方针对此 bypass 发布了新的 patch,但 Stefan Esser 表示新 patch 通过改变处理方式最终化解了此漏洞,但其提供的过滤函数 safeUnserialize() 依旧是存在安全问题的。虽然 Stefan Esser 没有透漏问题具体所在,但笔者通过查看相关 PHP 源码,发现 PHP 在对 string 进行序列化与反序列化处理过程中存在语法解析不一致的问题,这有可能会导致很严重的安全问题,同时也可以很容易的 bypass safeUnserialize() 函数的过滤。

i. PHP string serialize() 相关源码分析

------------------------------------

{% highlight c %}

	static inline void php_var_serialize_string(smart_str *buf, char *str, int len) /* {{{ */
	{
		smart_str_appendl(buf, "s:", 2);
		smart_str_append_long(buf, len);
		smart_str_appendl(buf, ":"", 2);
		smart_str_appendl(buf, str, len);
		smart_str_appendl(buf, "";", 2);
	}

{% endhighlight %}

通过上面的代码片段可以看到 serialize() 对 string 序列化处理方式如下:

{% highlight php %}

	$str = 'ryatsyne';
	var_dump(serialize($str));
	// $str serialized string output
	// s:8:"ryatsyne";

{% endhighlight %}

ii. PHP string unserialize() 相关源码分析

---------------------------------------

unserialize() 函数对 string 的反序列化则分为两种,一种是对 `s:` 格式的序列化 string 进行处理:

{% highlight c %}

	switch (yych) {
    	...
		case 's':	goto yy9;
		...
	yy9:
		yych = *(YYMARKER = ++YYCURSOR);
		if (yych == ':') goto yy46;
		goto yy3;
		...
	yy46:
		yych = *++YYCURSOR;
		if (yych == '+') goto yy47;
		if (yych = ':') goto yy18;
	yy48:
		++YYCURSOR;
		if ((YYLIMIT - YYCURSOR) = ';') goto yy18;
		yych = *++YYCURSOR;
		if (yych != '"') goto yy18;
		++YYCURSOR;
		{
		size_t len, maxlen;
		char *str;
		
		len = parse_uiv(start + 2);
		maxlen = max - YYCURSOR;
		if (maxlen 

另一种是对 S: 格式的序列 string 进行处理(此格式在 serialize() 函数序列化处理中并没有定义):

{% highlight c %}

	static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen)
	{
		size_t i, j;
		char *str = safe_emalloc(*len, 1, 1);
		unsigned char *end = *(unsigned char **)p+maxlen;
		
		if (end = end) {
				efree(str);
				return NULL;
			}
			if (**p != '') {
				str[i] = (char)**p;
			} else {
				unsigned char ch = 0;
				
				for (j = 0; j = '0' && **p = 'a' && **p = 'A' && **p 

从上面的代码片段可以看到 unserialize() 对序列化后的 string 反序列化处理如下:

{% highlight php %}

	$str1 = 's:8:"ryatsyne";';
	$str2 = 's:8:"ryatsyne"t';
	$str3 = 'S:8:"7279617473796e65"';
	var_dump(unserialize($str));
	// $str1, $str2 and $str3 unserialized string output
	// ryatsyne;

{% endhighlight %}

iii. 语法解析处理不一致导致的安全隐患

-----------------------------

从上述分析过程可以看到 PHP 在反序列化 string 时没有严格按照序列化格式 s❌"x"; 进行处理,没有对 " 后面的是否存在 ; 进行判断,同时增加了对十六进制形式字符串的处理,这样前后处理的不一致让人很费解,同时由于 PHP 手册中对此没有详细的说明,大部分程序员对此处理过程并不了解,这可能导致其在编码过程中出现疏漏,甚至导致严重的安全问题。

回到文章开头提到的 IPB 漏洞上,利用这个 funny feature of PHP 可以很容易的 bypass safeUnserialize() 函数的过滤:)

{% highlight php %}

    * mixed safe_unserialize(string $serialized)
    * Safely unserialize, that is only unserialize string, numbers and arrays, not objects
    *
    * @license Public Domain
    * @author dcz (at) phpbb-seo (dot) com
    */
    static public function safeUnserialize( $serialized )
    {
        // unserialize will return false for object declared with small cap o
        // as well as if there is any ws between O and :
        if ( is_string( $serialized ) && strpos( $serialized, "" ) === false )
        {
            if ( strpos( $serialized, 'O:' ) === false )
            {
                // the easy case, nothing to worry about
                // let unserialize do the job
                return @unserialize( $serialized );
            }
            else if ( ! preg_match('/(^|;|{|})O:[+-0-9]+:"/', $serialized ) )
            {
                // in case we did have a string with O: in it,
                // but it was not a true serialized object
                return @unserialize( $serialized );
            }
        }
 
        return false;
    }
    
    // a:1:{s:8:"ryatsyne"tO:8:"ryatsyne":0:{}}
    // 只要构造类似的序列化字符串就可以轻易突破这里的过滤了
        
{% endhighlight %}

iiii. 参考

----------

* [1][http://seclists.org/bugtraq/2012/Nov/17](http://seclists.org/bugtraq/2012/Nov/17)

* [2][http://adminextra.com/threads/ip-board-3-1-x-3-2-x-and-3-3-x-hacked.6125/](http://adminextra.com/threads/ip-board-3-1-x-3-2-x-and-3-3-x-hacked.6125/)

* [3][http://twitter.com/i0n1c](http://twitter.com/i0n1c)

文章来源于lcx.cc:PHP string序列化与反序列化语法解析不一致带来的安全隐患

相关推荐: 【VB】VB高速全盘搜索文件 同时搜索多文件

    VB高速全盘搜索文件,VB高速全盘文件搜索,VB高速搜索全盘文件,VB同时搜索多文件,VB多文件同时搜索,VB高速搜索文件,VB全盘搜索文件,VB高速搜索全盘,VB高速搜索文件,VB同时搜索文件,VB搜索多文件,VB多文件搜索,VB同时搜索,VB文件搜…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年4月3日19:27:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PHP string序列化与反序列化语法解析不一致带来的安全隐患http://cn-sec.com/archives/322630.html

发表评论

匿名网友 填写信息