在之前打帕鲁杯的时候遇到了,php写入文件来修改session进行伪造的题目。今天不知道学什么突然就想到了session反序列化我还没水过博客,于是写下这篇学习博客

php session介绍

首先我们都知道session是以文件的形式存储在服务端的,文件的内容是经过序列化后的数据。而存储的具体格式主要与下面几个php.ini设置有关

1
2
3
4
session.save_path:这是session文件的储存路径
session.auto_start:这个开关是指定是否在请求开始时就自动启动一个会话,默认为Off;如果它为On的话,相当于就先执行了一个session_start(),会生成一个session_id,一般来说这个开关是不会打开的
session.save_handler:这个是设置用户自定义session存储的选项,默认是files,也就是以文件的形式来存储的
session.serialize_handler:这是最重要的部分,定义用来序列化/反序列化的处理器名字,默认使用php,还有其他引擎,且不同引擎的对应的session的存储方式不相同,默认是php

session.serialize_handler

这个设置主要定义使用什么处理器来对内容进行存储不同的处理器存储格式不同

处理器名称 格式 存储结果
php 键名+竖线+序列化处理后的内容 name|s:6:”hahaha”;
php_binary 键名的长度对应的ASCII字符+键名+经过serialize()函数反序列处理的值 names:6:”hahaha”;
php_serialize 经过 serialize() 函数反序列处理的数组 a:1:{s:4:”name”;s:6:”hahaha”;}

漏洞原理

我们通过下面这个DEMO进行讲解

我们先来看一下session_start()函数的定义

会发现每次向服务器用GET,POST,COOKIE的方法来传入sessionid,都会重启session服务并将session文件的内容进行反序列化存储在$_SESSION里。
当然在反序列化正常的赋值存储的session值并不会出现问题,但是如果一个web的不同路由采用了不同的处理器这就有可能导致本不该杯反序列化的内容杯反序列化。
当我们给a传入|O:1:”A”:1:{s:1:”f”;s:5:”hahah”;}在访问flag.php时由于其处理器为php这就导致了其会将|后的进行解析为序列化语句而不是字符串从而进行反序列化。

无$_SESSION变量的赋值

在没有赋值代码时我们可以利用session上传进度来进行session的上传

我们只要在发文件的同时post一个session.upload_progress.name的同名变量

form表单如下

1
2
3
4
5
6
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="submit" />
</form>

注意因为表单没有cookie所以我们要手动添加PHPSESSID
但是其上传后内容会很快被清空所以我们要不断发包


可以看到post的value被存储了起来
那么我们便可以在无法对$_SESSION赋值时使用这个来上传session文件从而进行session反序列化。

例题

因为没有找到题目所以先放着