本文目录导读:

PHP会话反序列化漏洞是一个重要的安全问题,让我详细介绍。
漏洞原理
会话存储格式
PHP会话数据在文件中以特定格式序列化存储:
// 默认格式(php)
username|s:5:"admin";user_id|i:123;
// php_serialize格式
a:2:{s:8:"username";s:5:"admin";s:7:"user_id";i:123;}
// php_binary格式
usernames:5:"admin";
存储引擎差异
// php.ini配置 session.serialize_handler = php // 或 session.serialize_handler = php_serialize // 或 session.serialize_handler = php_binary
漏洞场景
处理器不匹配漏洞
// 攻击场景:写入和读取使用不同的处理器
<?php
// session.php - 使用php_serialize处理
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['data'] = $_POST['data'];
?>
<?php
// read.php - 使用php处理
ini_set('session.serialize_handler', 'php');
session_start();
var_dump($_SESSION['data']);
?>
利用Payload构造
// 当php_serialize写入,php读取时
POST data: |O:8:"stdClass":0:{}
a:1:{s:4:"data";s:22:"|O:8:"stdClass":0:{}";}
// php处理器解析时,会创建stdClass对象
实际攻击案例
对象注入攻击
class User {
public $username;
public $isAdmin;
function __destruct() {
// 危险操作
if ($this->isAdmin) {
// 提升权限
}
}
}
// 攻击载荷
|O:4:"User":2:{s:8:"username";s:5:"admin";s:7:"isAdmin";b:1;}
利用SESSION上传文件
// 攻击思路:通过session文件路径
session.upload_progress.enabled = On
// 利用上传进度功能
<form>
<input type="file" name="file">
<input type="text" name="PHP_SESSION_UPLOAD_PROGRESS">
</form>
// 构造恶意session
PHP_SESSION_UPLOAD_PROGRESS|O:4:"User":2:{s:8:"username";s:5:"admin";s:7:"isAdmin";b:1;}
防御措施
统一处理器
// php.ini配置
session.serialize_handler = php_serialize
// 或在代码中统一设置
ini_set('session.serialize_handler', 'php_serialize');
输入验证和过滤
// 对$_SESSION赋值前进行验证
function safe_session_set($key, $value) {
if (is_string($value)) {
// 过滤危险字符
$value = str_replace(['|', ':'], '', $value);
}
$_SESSION[$key] = $value;
}
使用安全配置
// php.ini安全配置 session.use_strict_mode = 1 session.use_only_cookies = 1 session.cookie_httponly = 1 session.cookie_secure = 1 session.sid_length = 128 session.sid_bits_per_character = 6
对象注入防护
// 使用allowed_classes限制反序列化 $data = unserialize($string, ['allowed_classes' => false]); // 或自定义限制 $allowed_classes = ['User', 'Product']; $data = unserialize($string, ['allowed_classes' => $allowed_classes]);
检测方法
代码审计检查点
# 搜索SESSION赋值 grep -r "\$_SESSION" /var/www/html/ # 搜索反序列化函数 grep -r "unserialize\|serialize" /var/www/html/ # 检查session配置 php -i | grep "session.serialize_handler"
安全漏洞扫描
// 测试代码
<?php
// 检查session处理器是否统一
function check_session_security() {
$handler = ini_get('session.serialize_handler');
echo "当前处理器: " . $handler . "\n";
// 检查是否允许危险对象
$session_content = file_get_contents(session_save_path() . '/sess_' . session_id());
if (preg_match('/O:\d+:/', $session_content)) {
echo "警告: 可能存在对象注入风险\n";
}
}
?>
最佳实践
-
统一使用php_serialize处理器
-
永远不要信任用户的Session数据
-
对反序列化进行白名单限制
-
定期清理session文件
-
使用框架的session管理组件
这个漏洞的核心在于不同序列化处理器之间的格式差异,务必保持统一配置。