这篇文章将为大家详细讲解有关如何进行thinkphp6的另反序列化分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
转发之前分析过tp6的一个链;当时是利用__toString方法去进行的中转,从而实现前后两个链的链接,这次是两个另外链条;利用的是可控类下的固定方法进行中转;开始分析;
首先环境可以作曲家一键搭建,然后php想跑进行跑起来就可;
文本首先的想法就是利用析构函数进行最开始的触发,然后一路追踪魔法函数去进行一步一步的推导,首先找到魔法函数在AbstractCache类下;
protected autosave 美元;=,真的; public function  __destruct () { ,,,if (!, $ this→自动保存),{ ,,,,,,,这个美元→保存(); ,,,} }
其代码如上;可以看到autosave可以可控;这里我们可以手动给其复制为假,从而可以触发保存方法;
回溯保存方法;在CacheStore中找到了保存方法;具体代码如下;
public function 保存() { ,,,contents 美元;=,$ this→getForStorage (); ,,,这美元→存储→设置($ this→键,,内容、美元,美元这→到期); }
可以看到其调用了getForStorage方法,然后将其赋值给美元内容变量。这里追随一下这个方法;
public function getForStorage () ,,,{ ,,,,,,,cleaned 美元;=,$ this→cleanContents ($ this→缓存); ,,,,,,,return json_encode([清洗,美元,美元这→完成]); }
发现首先调用了cleanContents方法,然后在调用了json_encode方法,这里首先回溯一下cleanContents方法;
public function cleanContents (array $内容) ,,,{ ,,,,,,,cachedProperties 美元;=,array_flip ([ ,,,,,,,,,,,& # 39;path & # 39;,, & # 39;目录名# 39;,,& # 39;basename # 39;,, & # 39;扩展# 39;,,& # 39;文件名# 39; ,,,,,,,,,,,& # 39;大小# 39;,,& # 39;mimetype # 39;,, & # 39;能见度# 39;,,& # 39;时间戳# 39;,,& # 39;类型# 39; ,,,,,,,,,,,& # 39;md5 # 39; ,,,,,,,); ,,,foreach (contents 美元;as path 美元;=祝辞,美元对象),{ ,,,,,,,if (is_array(对象)美元),{ ,,,,,,,,,,,内容美元(美元路径),=,array_intersect_key($对象,cachedProperties美元); ,,,,,,,} ,,,} ,,,return $内容; }
首先在这里看到了array_flip方法;这个方法是将数组的键名和键值进行替换,然后数组赋值给美元cachedProperties变量,然后将我们传入的参数按照路径和对象的美元格式来进行各个遍历,然后将键名经过is_array方法的判断如果为真则进行后续的函数处理,否则就直接返回$内容这个数组;经过这一系列操作完之后,最终是返回到了拯救函数里,然后接着去进行$ this→存储→设置(内容、美元$ this→键,这→到期);这里我们发现商店也可控,那么就有两种思路,第一个就是去实例化一个有集方法的类,或者我们实例化一个存在__call方法的类,从而可以因为访问不存在的方法去调用电话到魔术方法;这里我们先找到一个有集方法的类,在类文件中找到:
public function 设置(名称、美元,美元的价值,美元expire =, null): bool { ,,,这个→美元writeTimes + +; ,,,if (is_null($)到期),{ ,,,,,,,expire 美元;=,$ this→选项(& # 39;到期# 39;); ,,,} expire 美元,,,,,,=,$ this→getExpireTime(到期美元); ,,,filename 美元;=,$ this→getCacheKey($名称); ,,,dir 美元;=,目录名($ filename); ,,,if (! is_dir (dir)美元),{ ,,,,,,,try { ,,,,,,,,,,,mkdir (dir美元,0755,,真的); ,,,,,,,},catch (\ Exception $ e), { ,,,,,,,,,,,//,创建失败 ,,,,,,,} ,,,} ,,,data 美元;=,$ this→序列化(美元值); ,,,if ($ this→选项(& # 39;data_compress& # 39;),,,, function_exists (& # 39; gzcompress& # 39;)), { ,,,,,,,//数据压缩 ,,,,,,,data 美元;=,gzcompress ($ data, 3); ,,,} data 美元,,,,,,=,“& lt; ? php \ n//?只sprintf (& # 39; % 012 d # 39;,,到期美元),只“\ n 退出();?祝辞\ n",只美元数据; ,,,result 美元;=,写入(文件名,美元,美元数据); ,,,if (结果),{ ,,,,,,,函数(); ,,,,,,,return 真实; ,,,} ,,,return 假; }
这里可利用点在后面的序列化方法;直接追溯一下,