十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PHP Session 反序列化:防御加固、审计套路与总结

PHP Session 反序列化:防御加固、审计套路与总结 一、防御清单按性价比排序1.1 根除格式错位最重要Session 反序列化能成立的前提是写与读的 serialize_handler 不一致。只要全链路统一就断掉了错位解析的物理基础。统一session.serialize_handler能全站统一就统一推荐统一为php_serialize它格式最规范、不存在逐键|分隔的歧义各入口/各 SAPI/CLI 与 Web 的 php.ini 要一致不要在部分页面用ini_set(session.serialize_handler, ...)临时改改了就极易和别的页面错位更换 session 存储后端files→Redis 等时确认旧数据已清空避免旧格式文件被新后端读取。1.2 不要让用户可控数据进 session或至少别原样进业务上少把请求参数直接$_SESSION[x] $_POST[x];。若必须存做校验/白名单/转义尤其警惕|与序列化特征串。1.3 收敛任意文件包含面Session 反序列化的两条实战链路最终都依赖能写文件 能 include 文件。堵住 LFI/RFI、对 include 路径做白名单能同时废掉写马链路与大部分探测。1.4 会话层面加固session.use_strict_mode 1不接受服务器不认识的 session id增加自定 id 预测文件名的难度严格控制 session 文件目录权限只允许运行用户读写别放在 web 可访问/可下载的目录session.save_path不要指向 web 根目录之类能被直接 URL 访问的地方。1.5 upload_progress 加固如果确实用不到session.upload_progress.enabled Off ; 或至少 session.upload_progress.cleanup On ; 确保上传结束立即清 session.upload_progress.freq 1% session.upload_progress.min_freq 1用不到进度条就干脆关掉能删掉一个不需要业务漏洞的 session 写点。1.6 代码层纵深反序列化对象做允许类白名单PHP 7.4 支持在session_start()里配——不对那是unserialize()的allowed_classes选项Session 解码默认不过滤类。若可行用自定义 session handler / 反序列化前做类白名单校验能挡住未知类注入及时升级 PHP跟进官方 session 相关修复安全编码规范里明确禁止把不可信内容无差别写入 session这条红线。一句话记住防御核心统一 handler 格式 用户输入不进 session 别给文件包含 关 upload_progress。二、审计视角怎么快速发现这种洞Step 1 找 session 的写与读分别用什么 handler grep serialize_handler / ini_set / session_start([serialize_handler 看不同页面是否一致 —— 不一致 有戏 ​ Step 2 找可控数据能否进 session 文件 a. $_SESSION[...] $_REQUEST/$_POST/$_GET/可拼接串 ... b. 无业务写点 → 看 upload_progress.enabled 是否为 On能否用上传写点 ​ Step 3 判断写点内容能否承载 | 序列化对象有没有过滤/转义 | ​ Step 4 找可利用类 / POP 链危险 __destruct/__wakeup/__toString/...能 autoload 注意 php_serialize 写 php 读 时对象类必须真实存在才会触发 ​ Step 5 构造 payload → 写点提交 → 触发读取 → 验证CTF 题面上通常给两条线索帮你走完 Step 1一个文件里ini_set(session.serialize_handler, php_serialize)存了可控值另一个文件/入口只有默认的session_start()。只要把两者用同一个PHPSESSID串起来就是完整攻击。三、CTF 常见题型套路怎么认出来、突破口在哪出题套路特征线索突破口处理器错位最经典页面 A 用 php_serialize 存用户可控值页面 B 默认 session_start提示词常出现 php_serialize构造\|O:...注入对象upload_progress 注入给了上传点但没明显业务写 session或 hint 提 upload_progress文件名/PHP_SESSION_UPLOAD_PROGRESS 字段塞 payloadupload_progress LFI存在include $_GET[file]写马 include sess_id getshell反序列化 POP 链考察给了好几个类/危险函数sink 定位 串链组合题全链路一个点触发反序列化要求最终 RCE从注入对象到代码执行要自己串写点→错位→POP→sink做题建议顺序不管多花哨的题都适用先读源码确认session 相关配置与写点别一上来就找 POP 链先确认入口成不成立用本地同版本 PHP 把 payload 打在本地 session上xxd看文件字节对不对、能不能触发再对着远程提交利用失败时先回来查文件字节是否真写对了。四、版本与配置差异速查关注点说明php_serialize处理器PHP ≥ 5.5.4session.upload_progress.*PHP ≥ 5.4默认 enabledOn解码失败行为PHP ≥ 7 报Failed to decode session object. Session has been destroyed.并清空__unserialize()优先于__wakeup()PHP ≥ 7.4session id 合法字符A-Z a-z 0-9 - ,实测含下划线会被拒session 默认文件路径Debian/Ubuntu/var/lib/php/sessions一般发行版/tmp可用session.save_path改session 文件命名sess_session_id五、推荐资源官方为主PHP 官方手册中文Session 配置说明https://www.php.net/manual/zh/session.configuration.phpsession.serialize_handlerhttps://www.php.net/manual/zh/session.configuration.php#ini.session.serialize-handler会话上传进度https://www.php.net/manual/zh/session.upload-progress.phpsession_start()https://www.php.net/manual/zh/function.session-start.php魔术方法、绕过、POP 链两篇。关于错位注入 /|分隔的经典思路可以搜中文社区关键字session 反序列化 php_serialize php 竖线注入、upload_progress session 写马 LFI结合多篇 writeup 对照理解不同作者对落盘时机的描述有出入以自己实测为准。练习环境本地php -S Docker 自建不要用带非法字符的 session id跑完记得清理 php -S 后台进程。六、最后一张图全系列知识怎么串成记忆看一个请求/一个页面 → handler 谁写的谁读的 │ 不一致 ▼ 能把可控字符串(含 | )弄进 session 文件吗 业务写点? / upload_progress? / LFI 触发? │ 能 ▼ 文件里第一个 | 之后的字节 你的对象序列化 ▼ php_var_unserialize 创建对象 → 魔术方法 → POP 链 → sink(RCE)
返回列表