本文首发于先知社区,点击原文链接可查看原文
session 概念: 一般称为会话控制。 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 页之间跳转时,存储在 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 页时,如果该用户还没有会话,则 服务器将自动创建一个 对象。当会话过期或被放弃后,服务器将终止该会话。
PHP session概念: 是一个特殊的变量,用于存储有关用户会话的信息,或更改用户会话的设置。 变量保存的信息是单一用户的,并且可供应用程序中的所有页面使用。它为每个访问者创建一个唯一的 ,并基于这个 来存储变量。 存储在 中,亦或通过 进行传导。
当开始一个会话时, 会尝试从请求中查找会话 (通常通过会话 ), 如果请求中不包含会话 信息, 就会创建一个新的会话。会话开始之后, 就会将会话中的数据设置到 变量中。当 停止的时候,它会自动读取 中的内容,并将其进行序列化, 然后发送给会话保存管理器来进行保存。
默认情况下, 使用内置的文件会话保存管理器()来完成会话的保存。也可以通过配置项 来修改所要采用的会话保存管理器。对于文件会话保存管理器,会将会话数据保存到配置项 所指定的位置。
可以通过调用函数 来手动开始一个会话。如果配置项 设置为1, 那么请求开始的时候,会话会自动开始。本执行完毕之后,会话会自动关闭。同时,也可以通过调用函数 来手动关闭会话。
在 的安装目录下面找到 文件,这个文件主要的作用是对 进行一些配置
PHP 的 中的内容默认是以文件的方式来存储的,存储方式就是由配置项 来进行确定的,默认是以文件的方式存储。
存储的文件是以 来进行命名的,文件的内容就是 值的序列化之后的内容。
化引擎的,除了默认用来设置 的序列化引擎的,除了默认的 引擎之外,还存在其他引擎,不同的引擎所对应的 的存储方式不相同。
session.serialize_handler有如下三种取值
在 中默认使用的是 引擎,如果要修改为其他的引擎,只需要添加代码,示例代码如下:
以如下代码为例,查看不同存储引擎存储的结果
php_binary
php
php_serialize
当网站序列化存储 与反序列化读取 的方式不同时,就可能导致 反序列化漏洞的产生。一般都是以 序列化存储 , 以 反序列化读取 ,造成反序列化攻击。
例子
s1.php
s2.php
s1.php 使用的是 存储引擎,s2.php 使用的是 存储引擎(页面中没有设置存储引擎,默认使用的是 中 设置的值,默认为 )
我们可以往 s1.php 传入如下的参数
此时使用的是 存储引擎来序列化,存储的内容为
接着访问s2.php,使用的是 存储引擎来反序列化,结果
这是因为当使用 引擎的时候, 引擎会以 | 作为作为 和 的分隔符,那么就会将作为 的 ,将作为 ,然后进行反序列化。
访问s2.php为什么会反序列化?这里可以可以看看官方文档
那串 不符合"正常"的被反序列化的字符串规则不会报错吗?这里提到一个 的特性,在执行 的时候,如果字符串前面满足了可被反序列化的规则即后续的不规则字符会被忽略。
上面的例子直接可以给 赋值,那当代码中不存在给 赋值的时候,又该如何处理?
查看官方文档,可知还存在 PHP 还存在一个 机制,可以在中创建一个键值对,其中的值可以控制。
以 Jarvis OJ 平台的 PHPINFO 题目为例
环境地址:http://web.jarvisoj.com:32784/
index.php
存在 phpinfo.php 文件,由此可知 为 On, 为 ,与 index.php 页面所用的 PHP 存储引擎不同,存在反序列化攻击。
为 ,可以本地创建 form.html,一个向 index.php 提交 POST 请求的表单文件,其中包括 变量。
form.html
使用 bp 抓包,在 的 值123后面添加 | 和序列化的字符串
查看根目录文件
查看根目录路径
读取 flag
利用条件:存在文件包含, 文件的路径已知,且文件中的内容可控。 文件的路径可从 中得知
或者进行猜测
例子1:session.php
include.php
往 session.php 传入一句话,写入 文件中
在 中 值为 ,即 存储的文件名为 ,路径可以猜测一下,这里为
include.php 文件包含 存储文件
例子2:XCTF2018-Final_bestphp这里就取其中的小部分代码bestphp.php
这里设置了 ,限制了我们读取文件的范围,这里 文件是保存在 下,不在读取的范围里,这里可以考虑修改一下 文件存储的位置。
session_start() 函数从 开始增加了 参数,会覆盖 php.ini 中的配置。
利用 覆盖 php.ini 文件中的默认配置 的值,并写入
成功包含 session 文件
其实这个操作也可以由 函数来完成,但是这个函数传入的参数是个字符串,不适用于此题。
利用条件:知道所使用的 存储引擎,以及 文件内容可控。
这里就以2020虎符杯-babyupload 为例
index.php
这是一个存在上传和下载文件的功能的文件,只有当 才能获取 。我们可以通过下载查看 文件所使用的存储引擎,然后通过相同的存储引擎伪造为 ,上传 文件 ,获取 。
首先下载 文件,文件名为
可知使用的是 ,内容为:
猜测我们只要上传一个 文件内容为:
发现如果不上传 参数,会直接拼接上传的文件名+,如果把上传文件名设置为 ,并且不传递 参数,就可以得到,这就可以当成 文件。
是根据文件内容得到的 值
本地创建一个文件名为sess:
上传 sess 文件
计算 hash 值
文件名为 ,尝试下载访问,如下可知已经上传成功。
现在就差 success.txt, 可以把 参数设置为 success.txt,将 success.txt 变成一个目录,从而绕过了限制。