沉铝汤的破站

IS LIFE ALWAYS THIS HARD, OR IS IT JUST WHEN YOU'RE A KID

PHP-Session反序列

0x00 前言


本来是昨天要写的文章,结果因为太懒了,就鸽了,今天补回来。真是一条大懒狗。

0x01 PHP-Session


创建流程

关于什么是session,这里就不说了。php中创建session的流程直接看下面这张图,或许会比我自己写的更加直观。

img

存储机制

php中的存储机制的设定,依靠的是php.ini中的session.sava_handler进行设置的,默认采用的是文件形式存储。php会将session存储在session.save_path所设定的路径目录之中,并以sess_sessionid(eg: sess_CheNLvTaNGisFool)的形式命名。

存储形式

当php采用不同的处理器设定时,所存储的session形式也略有不同,处理器的设定由php.ini中的session.serialize_handler选项进行设定。php中有三种不同的处理器可供使用,下面是利用三种不同处理器进行创建session的详细结果:

php

采用这种处理器的时候,存储格式为: 键名+竖线+经过serialize()函数处理的值

image-20210412160950546

php_binary

这种处理器的存储格式为:键名的长度对应的ascii字符+键名+serialize()函数序列化的值

image-20210412161841918

因为”chenlvtang”长度为10,十六就进制就是0a,对应的Ascii是换行,所以看到有一个换行。

php_serialize

这个处理器有版本要求,PHP 版本大于5.5.4时,可以使用,它的存储方式为:经过serialize()函数序列化数组

image-20210412162956001

0x02 使用不同的处理器引发的反序列化漏洞


上文说到了几种不同处理器的不同格式,那如果同时对一个session进行不同处理的时候,会不会有可能产生漏洞呢?

Session变量可控时

下面是一个网站的两个文件:

demo1.php:

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

demo2.php:

<?php
session_start();
class student{
    var $name;
    var $age;
    function __wakeup(){
        echo $this->name;
    }
}
?>

demo1.php中由于某种需求采用了另一种处理器,但在demo2.php中未进行设定,这样会默认采用php处理器,这时,两个文件采用的处理器就不同了。这里还需要补充一个关于session_start()的小知识:

当会话自动开始或者通过 session_start() 手动开始的时候, PHP 内部会调用会话管理器的 open 和 read 回调函数。 会话管理器可能是 PHP 默认的, 也可能是扩展提供的(SQLite 或者 Memcached 扩展), 也可能是通过 session_set_save_handler() 设定的用户自定义会话管理器。 通过 read 回调函数返回的现有会话数据(使用特殊的序列化格式存储), PHP 会自动反序列化数据并且填充 $_SESSION 超级全局变量。

可以看到,session_start函数会将已有的会话数据进行反序列,这里就是我们可以利用的反序列化点了。demo2中的处理器php会用|进行区分键和序列化的值,所以如果我们现在demo1中生成一个session,并在其中插入|,那么,再访问demo2,他是不是反序列化已有会话中序列化的值呢?

首先我们先访问demo1,并构造payload传值:
image-20210412203845362

此时的session为:a:1:{s:4:"test";s:66:"|O:7:"student":2:{s:4:"name";s:10:"chenlvtang";s:3:"age";s:1:"3";}";}

然后我们访问demo2:

image-20210412204225651

可以看到成功调用了__wakeup,完成了反序列化。

Session变量不可控时

上文中,当session可控时,一切都是这么的简单。但如果我们控制不了session变量的时候,又该怎么做呢?

神说“要有光”,于是便有了光。既然我们现在不可控,那么我们是否能通过一种方法,从而实现对session变量的控制呢?

image-20210412210350918

确实是有的,但是我不准备在这写,我只写一下他的名字: session.upload_progress

0x03 参考文章


PHP_Session反序列化漏洞

Y4tacker师傅