PHPSESSION机制以及反序列化
前言
之前接触Session的时候,没有仔细去了解,最近又接触到了php的session反序列化,于是再拿出来梳理一下。
session是干嘛的
设想一个场景,开启一个会话,怎么让会话持续呢?比如一个用户登录一个网站去买一本书,你怎么知道是这个用户要买书而不是另外一个用户呢?而session会存储特定对象的信息,session 其实也是一个身份验证机制。
session咋起作用
在PHP中得调用session_start() 函数来手动开启session机制,当第一次去访问网站时,第一次的响应包里面会携带set-cookie字段,返回一个sessionid,然后服务器会创建与sessionid同名的文件,里面储存了该用户的会话信息。以此来维持会话,且同一个用户访问这个服务器上任何一个页面的时候都会使用同一个sessionid 。如果觉得每一个页面使用session_start比较麻烦,可以在 php.ini配置里将 session.auto_start=1 来开启
session相关配置
1 | session.save_handler --- session的保存形式,默认为files,以文件形式保存 |
session反序列化
session序列化存储所用的处理器有三种:
- php —存储格式:键名+竖线+经过serialize()函数序列化后的值
- php_binary —存储格式:键名长度对应的ASCII字符+键名+经过serialize()函数序列处理的值
- php_serialize —存储格式:经过serialize()函数序列化处理的值
存储和取出用的是同一个处理器,不会造成安全问题,而使用不同的处理器就会引发一些安全问题了,下面通过一个典型的demo来解释上面提到的几点
Demo
1 | //demo.php |

当我传入?My0n9s=xs时,可以看到本地生成了一个与sessionid同名的sess_xxx文件,我使用的是phpstudy集成环境,默认路径在 D:\phpStudy\PHPTutorial\tmp\tmp上

可以看到php处理器 序列化存储的结果为 My0n9s|s:2:"xs"; 换一下处理器可以看到,php_serialize处理器对应的序列化结果为a:1:{s:6:"My0n9s";s:2:"xs";} ,php_binary处理器对应的序列化结果为:My0n9ss:2:"xs"; 因为ASCII 值6 对应的是ACK这里没显示出来。
我们再来看看由于不同处理器造成的反序列化问题
1 |
|
demo1.php 我们使用 php_serialize来进行序列化存储
1 | //demo2.php |
demo2.php 我们使用php处理器
然后我们本地构造一个payload:
1 |
|
将生成的传入到demo1.php,查看本地的sess_xxxx文件得到值:
a:1:{s:6:"My0n9s";s:59:"|O:7:"Student":2:{s:4:"name";s:8:"xiaoming";s:3:"age";i:8;}";}
我们再去访问 demo2.php 可以看到:

成功反序列化。原因在于 php处理器在遇到| 时,会直接把它后面的字符串进行反序列化处理。
造成session反序列化的原因是因为序列化存储时用到的处理器和取出时反序列化的处理器不一致导致的。
采坑
我之前一直在想,序列化和反序列化是什么来触动他们发生的,后来才知道是 session_start 函数来触发的。
官方文档关于session_start的解释:
1 | session_start() 会创建新会话或者重用现有会话。 如果通过 GET 或者 POST 方式,或者使用 cookie 提交了会话 ID, 则会重用现有会话。 |
重点在最后一句:
PHP 会自动反序列化数据并且填充 $_SESSION 超级全局变量
要开始肝课设了,老拖延症了。