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
板子
|
|