PHP session反序列化问题

wen PHP项目 2

本文目录导读:

PHP session反序列化问题

  1. 漏洞原理
  2. 漏洞场景
  3. 实际攻击案例
  4. 防御措施
  5. 检测方法
  6. 最佳实践

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";
    }
}
?>

最佳实践

  1. 统一使用php_serialize处理器

  2. 永远不要信任用户的Session数据

  3. 对反序列化进行白名单限制

  4. 定期清理session文件

  5. 使用框架的session管理组件

这个漏洞的核心在于不同序列化处理器之间的格式差异,务必保持统一配置。

抱歉,评论功能暂时关闭!