ARTICLE DETAIL

资讯详情

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

萌新序列化反序列化看这篇

萌新序列化反序列化看这篇 一. 序列化与反序列化是什么简单一句话序列化 把内存里的对象 / 数据转成一段可保存的字符串反序列化 把这段字符串还原回内存里的对象。程序运行的时候变量、对象都只在内存里程序一关就没了。 如果想把对象存到文件、数据库或者通过网络传给别人不能直接丢内存对象所以就有了序列化序列化对象 → 字符串保存 / 传输 例PHP 的serialize()、Python 的pickle.dumps()反序列化字符串 → 还原成程序对象读取使用 例PHP 的unserialize()、Python 的pickle.loads()核心目的方便持久化存储、跨地方传输数据。二. 为什么会出现反序列化漏洞不是编程语言本身有缺陷是代码在读取序列化字符串时默认充分信任输入的数据。正常场景开发者自己序列化数据自己存之后自己读取反序列化数据可控不会有问题。危险场景反序列化的字符串来自用户可控输入GET/POST 参数、Cookie、文件上传内容等开发者直接把用户传过来的字符串丢进反序列化函数认为输入一定是合法可信的。 攻击者可以构造恶意序列化字符串当程序执行反序列化还原对象时会自动触发对象里的魔法方法执行我们想要的代码。重点漏洞根源 ——信任不可信的外部输入。三. 一眼识别哪些地方大概率存在反序列漏洞一PHP 反序列化 全特征识别PHP 是 CTF 反序列化出题最多的语言特征非常固定熟记即可秒判断。1. 高危核心触发函数unserialize($xxx)最核心、最高频考点几乎所有 PHP 反序列化题目入口函数作用是将序列化字符串还原为对象。unserialize(file_get_contents(xxx))读取文件内容并反序列化常见于文件存储 反序列化组合题型。unserialize($_COOKIE[xxx])Cookie 传参反序列化CTF 超级经典场景无过滤直接高危。unserialize($_GET[xxx])/unserialize($_POST[xxx])GET/POST 可控参数直接反序列化入门题标配。辅助对照函数出现代表题目存在序列化逻辑serialize()开发者正常序列化数据用的只出现这个没问题搭配 unserialize 且参数可控才存在漏洞。2. 代码可控场景满足「用户可以控制函数参数」就是可利用漏洞直接传入超全局变量unserialize($_GET[data])、unserialize($_POST[user])、unserialize($_COOKIE[info])二次处理可控数据接收用户参数简单赋值、过滤无安全过滤后传入反序列化函数$a $_GET[input]; $b $a; unserialize($b); //数据完全可控存在漏洞文件读取可控用户可上传文件、修改文件内容程序读取文件内容执行反序列化3. 页面明文特征标准格式O:类名长度:类名:属性数量:{属性键值对}真实样例O:4:User:2:{s:3:name;s:5:admin;s:3:pwd;s:6:123456;}简化格式部分题目会有短属性、空属性的序列化串核心开头一定是O:对象、a:数组4. 专属报错特征页面爆出以下错误直接是 PHP 反序列化题型unserialize() expects parameter 1 to be stringError: unserialize(): Error at offsetInvalid serialized data报错堆栈中出现unserialize函数名二Python 反序列化 识别Python 反序列化比 PHP 更危险几乎所有 pickle 反序列化函数可控 直接 RCE 命令执行1. 高危核心触发函数以下 pickle 模块函数参数可控直接利用pickle.loads(data)最主流考点接收字符串 / 字节串反序列化CTF Python 序列化核心入口pickle.load(fp)读取文件对象内容反序列化搭配文件上传、文件读取出题cPickle.loads()Python2 旧版本函数功能和 pickle 一致同样高危补充pickle.dumps()序列化生成字节串仅为辅助函数单独出现无危害2. 代码可控高频场景直接接收用户输入pickle.loads(request.args.get(data))、接收 POST、Header 参数反序列化读取用户上传文件打开用户上传的文件直接传入 pickle.load () 解析读取本地可控文件文件路径 / 内容可被用户修改触发反序列化3. 页面 数据包特征数据包中出现大量不可读二进制乱码pickle 序列化是二进制格式和 PHP 明文完全不同页面返回、Cookie、参数中存在规律的特殊字符\x80\x04\x95pickle 协议标准头部特征源码中导入import pickle模块90% 概率考察反序列化漏洞4. 专属报错特征pickle.UnpicklingErrorinvalid load keycould not find MARK报错堆栈包含pickle.loads、unpickler关键字四. 解题建议1. 魔法方法__construct: new新建对象才跑反序列化不跑 __wakeup : unserialize反序列化自动跑可通过属性数量绕过 __destruct : 对象销毁脚本结束自动跑pop链常用收尾 __toString : 对象被echo/当作字符串使用触发 __get : 读不存在/私有属性触发 __set : 给不存在/私有属性赋值触发 __call : 调用对象不存在的成员方法触发 __invoke : 把对象当成函数$obj()调用触发 __sleep : serialize序列化对象前触发 __isset : isset/empty检测不存在/私有属性触发 __unset : unset删除不存在/私有属性触发反序列化还原对象时会自动触发__wakeup对象销毁时触发__destruct。 漏洞利用的起点大多就是靠魔法方法自动执行代码。2. POP 链Property-Oriented Programming面向属性编程当魔法方法里没有直接可以执行命令的代码但是代码里很多类存在方法调用。 POP 链就是把多个类的属性、方法串起来从入口魔法方法开始一步步接力调用最终走到危险函数system()、eval()等拿到命令执行。ps:这个我也不太会在学习中写题中总结了一些链子你们也可以去网上找有很多但是一定要自己用有时一个链子可以修改用到其他题我这里贴一个示例?php namespace yii\rest { class IndexAction { public $checkAccess; public $id; } } namespace Faker { use yii\rest\IndexAction; class Generator { protected $formatters; } } namespace yii\db { use Faker\Generator; class BatchQueryResult { private $_dataReader; } } $a new yii\rest\IndexAction(); $a-checkAccess system; $a-id whoami; $b new Faker\Generator(); $b-formatters[close] [$a, run]; $c new yii\db\BatchQueryResult(); $c-_dataReader $b; echo serialize($c); echo \n.base64_encode(serialize($c)); ?五. 感兴趣可以读读这两篇这两篇讲的更详细我的这篇更像是初学者笔记https://www.plumephp.com/security-deserialization-rce/https://www.freebuf.com/articles/web/333697.html我的这篇还有许多不足和遗漏或者错误希望评论区一起探讨。
返回列表