PHP WDDX Serializier Data Injection Vulnerability

PHP 在把数组序列化为 WDDX 结构的过程中,没有对数组的键名严格限制,导致可以伪造对象的 WDDX 结构。

i 序列化对象


PHP 在把对象序列化为 WDDX 结构时,会做如下处理:

比如下面代码中的变量 $obj:

经过 wddx_serialize_value() 函数序列化的 WDDX 结构如下:

ii 序列化数组


PHP 把数组序列化为 WDDX 结构时,会做如下处理:

从上面的代码可以看到,数组序列化后的 WDDX 结构主要分为两种,一种是没有指定键名的数组的处理,比如下面代码中的变量 $arr:


经过 wddx_serialize_value() 函数序列化的 WDDX 结构如下:

另一种则是对指定键名的数组的处理,比如下面代码中的变量 $arr:

经过 wddx_serialize_value() 函数序列化的 WDDX 结构如下:

iii 伪造对象的 WDDX 结构


通过上面的分析,简单了解 WDDX 结构存储 PHP 数组和对象的具体格式,对象的存储格式和指定键名的数组的存储格式非常接近,区别只在于,对象的存储格式多了对类名的存储:

PHP 在把数组序列化 WDDX 结构过程中,仅仅调用了 php_escape_html_entities() 函数处理,然后直接构造 WDDX_VAR_S:

那么如果数组中存在一个值为 php_class_name 的键名,就可以构造出:

这时序列化的 WDDX 结构就和对象的一样了,如下面代码中的变量 $arr:

经过 wddx_serialize_value() 函数序列化的 WDDX 结构如下:

可以看到,序列化的 WDDX 结构和第一个例子中的 $obj 对象序列化的 WDDX 结构是一样的,也就说,通过一个特殊的数组伪造了一个对象的 WDDX 结构:)

iv 安全隐患


PHP 反序列化 WDDX 结构的处理过程类似于 unserialize() 函数,通过对特定的 WDDX 结构反序列化,可以生成一个对象,并执行类的 __wakeup() 方法(如果存在的话),在对象被销毁或者脚本执行结束时会执行类的 __destruct() 方法(如果存在的话),那么安全隐患随之而来。而比 unserialize() 函数更危险的是,反序列化过程和序列化过程都可能存在安全问题:)

i) 利用 wddx_deserialize() 函数

通过下面的方式,可以成功执行 __wakeup() 方法和 __destruct() 方法:)

ii) 利用 $_SESSION 进行序列化和反序列化

PHP 在存储和读取 $_SESSION 时会对数据进行序列化和反序列化,默认情况下与 serialize() 函数和 unserialize() 函数的处理方式相同,但是 PHP 提供了一个 session.serialize_handler 配置选项,可以使用 WDDX 格式进行序列化和反序列化:)

通过下面的方式,就可以伪造成对象的 WDDX 结构:)

from:http://www.80vul.com/pch/pch-014.txt