在php.ini中存在以下几个配置项:
session.save_path="" --设置session的存储路径 session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式) session.auto_start boolen --指定会话模块是否在请求开始时启动一个会话,默认为0不启动 session.serialize_handler string --定义用来序列化/反序列化引擎名字。默认使用php
例如:
session.save_path="D:\xampp\tmp" 表明所有的session文件都是存储在xampp/tmp下 session.save_handler=files 表明session是以文件的方式来进行存储的 session.auto_start=0 表明默认不启动session session.serialize_handler=php 表明session的默认序列化引擎使用的是php序列化引擎
不同的引擎所对应的session的存储方式不相同。php存储session的三种模式(序列化/反序列化引擎):
php_serialize (php≥5.5.4) | 经过serialize()函数序列化数组 |
php | 键名➕竖线➕经过serialize()序列化的值 |
php_biary | 键名长度对应的ascii字符➕键名➕serialize()序列化的值 |
在PHP中默认使用的是PHP引擎,如果要修改为其他的引擎,只需要添加代码ini_set('session.serialize_handler', '需要设置的引擎');
。
举栗说明:
<?php ini_set("session.serialize_handler","php"); session_start(); $_SESSION['shaw'] = $_GET['shaw']; ?>
运行该代码后,可看到请求头存在Cookie=a7d4f0vgjr1l1hr6aud13noae6
关于session的存储机制:
php中的session中的内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项
session.save_handler
来进行确定的,默认是以文件的方式存储。存储的文件是以
sess_sessionid
来进行命名的,文件的内容就是session值的序列话之后的内容。
在本地找到sess_a7d4f0vgjr1l1hr6aud13noae6
,查看内容:
简单记就是有竖线就是php类型。康康另一种模式(php_serialize
):
<?php ini_set("session.serialize_handler","php_serialize"); session_start(); $_SESSION['shaw'] = $_GET['shaw']; ?>
最后,看一下第三种(php_biary
):
<?php ini_set("session.serialize_handler","php_binary"); session_start(); $_SESSION['shaw'] = $_GET['shaw']; ?>
显示的是:shaws:3:"123";
由于shaw
的长度是4,4在ASCII表中对应的就是EOT
。根据php_binary的存储规则,最后就是shaws:3:"123";
CTF比赛中常考的session反序列化漏洞产生的原因简单来说就是序列化及反序列化处理器(引擎)设置使用不当。如果php
和php_serialize
这两个处理器混合起来使用,就会出现session反序列化漏洞。session_start会检测sess_sessionid中的内容是否符合引擎的格式,如果符合则对其反序列化,否则清空。
php_serialize
存储的反序列化字符可以引用|,如果这时候使用php
处理器的格式取出$_SESSION的值,|会被当成键值对的分隔符,在特定的地方会造成反序列化漏洞
当无可控的,可以修改sess_sessionid内容的点时,如果php配置满足以下三个条件(详见php的Bug #71101),仍可达到触发反序列化漏洞的目的:
session.serialize_handler
[session序列化存储所用处理器。]局部变量(Local)为php,全局变量为php_serializesession.upload_progress.cleanup
[一旦读取了所有POST数据,立即清除进度信息。](其值默认开启)关闭状态session.upload_progress.enabled
[将上传文件的进度信息存在session中。](其中默认开启)开启状态
session.upload_progress.enabled
本身的作用不大,其作用是检测文件的上传进度。但当一个文件上传时,同时POST一个与php.ini中session.upload_progress.name
同名的变量时(session.upload_progress.name
的变量默认值为PHP_SESSION_UPLOAD_PROCRESS),PHP检测到这种同名请求会在$_SESSION中添加一条数据,由此来设置session。
本地创建一个表单,网址写题目地址。
<!DOCTYPE html> <html> <body> <form action="http://example.com/" method="POST" enctype="multipart/form-data"> <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" /> <input type="file" name="file" /> <input type="submit" value="submit" /> </form> </body> </html>
访问该表单,上传文件的文件名写自己的payload,即精心构造的序列化的值,并记得把双引号转义。