PHP session反序列化漏洞
会话开始之后,PHP 就会将会话中的数据设置到 $_SESSION 变量中,如下述代码就是一个在 $_SESSION 变量中注册变量的例子:
|
|
当 PHP 停止的时候,它会自动读取 $_SESSION 中的内容,并将其进行序列化, 然后发送给会话保存管理器来进行保存。
默认情况下,PHP 使用内置的文件会话保存管理器来完成session的保存,也可以通过配置项 session.save_handler 来修改所要采用的会话保存管理器。 对于文件会话保存管理器,会将会话数据保存到配置项session.save_path所指定的位置。
PHP session的存储机制是由session.serialize_handler来定义引擎的,默认是以文件的方式存储,且存储的文件是由sess_sessionid来决定文件名的
session.serialize_handler定义的引擎有三种,如下表所示:
| 处理器名称 | 存储格式 |
|---|---|
| php | 键名 + 竖线 + 经过serialize()函数序列化处理的值 |
| php_binary | 键名的长度对应的 ASCII 字符 + 键名 + 经过serialize()函数序列化处理的值 |
| php_serialize | 经过serialize()函数序列化处理的数组 |
上述三种处理器中,php_serialize在内部简单地直接使用 serialize/unserialize函数,并且不会有php和 php_binary所具有的限制。 使用较旧的序列化处理器导致$_SESSION 的索引既不能是数字也不能包含特殊字符(| 和 !) 。
php 处理器
首先来看看session.serialize_handler等于 php时候的序列化结果,demo 如下:
|
|
序列化的结果为:session|s:7:"xianzhi";
session 为$_SESSION['session']的键名,|后为传入 GET 参数经过序列化后的值
php_binary处理器
再来看看session.serialize_handler等于 php_binary时候的序列化结果。
demo 如下:
|
|
为了更能直观的体现出格式的差别,因此这里设置了键值长度为 35,35 对应的 ASCII 码为#
序列化的结果为:#sessionsessionsessionsessionsessions:7:"xianzhi";
#为键名长度对应的 ASCII 的值,sessionsessionsessionsessionsessions为键名,s:7:"xianzhi";为传入 GET 参数经过序列化后的值
php_serialize 处理器
最后就是session.serialize_handler等于 php_serialize时候的序列化结果,同理,demo 如下:
|
|
序列化的结果为:a:1:{s:7:"session";s:7:"xianzhi";}
a:1表示$_SESSION数组中有 1 个元素,花括号里面的内容即为传入 GET 参数经过序列化后的值
bug
简单来说php处理器和php_serialize处理器这两个处理器生成的序列化格式本身是没有问题的,但是如果这两个处理器混合起来用,就会造成危害。
形成的原理就是在用session.serialize_handler = php_serialize存储的字符可以引入 | , 再用session.serialize_handler = php格式取出$_SESSION的值时, |会被当成键值对的分隔符,在特定的地方会造成反序列化漏洞。
例子:
定义一个session.php文件,用于传入 session值,文件内容如下:
|
|
存在另一个class.php 文件,内容如下:
|
|
这两个文件的作用很清晰,session.php文件的处理器是php_serialize,class.php文件的处理器是php,session.php文件的作用是传入可控的 session值,class.php文件的作用是在反序列化开始前输出Who are you?,反序列化结束的时候输出name值。
这两个文件如果想要利用php bug #71101,我们要在session.php文件传入|+序列化格式的值,然后再次访问class.php文件的时候,就会在调用session值的时候,触发此 BUG。
首先生成序列化字符串,利用 payload 如下
|
|
此时的 session内容如下:
a:1:{s:7:"session";s:44:"|O:7:"XianZhi":1:{s:4:"name";s:7:"xianzhi";}";}
再次访问class.php文件的时候,就会发现已经触发了php bug #71101
板子
|
|