php代码审计之YIXUNCMS2.0

介绍

该cms主要使用php5、mysql。建议使用xampp的集成环境。

url路由分析

从几个入口发现,都会直接包含php/index.php这个文件,所以从这个文件开始分析。前面几行做一个预处理和常量的定义,然后包含一些文件。一直到__autoload函数,用于自动加载类。然后解析url是从Prourl:parseurl()函数开始。我们跳转进入看看。

<?php	
	header("Content-Type:text/html;charset=utf-8");  //设置系统的输出字符为utf-8
	date_default_timezone_set("PRC");    		 //设置时区(中国)

	//PHP程序所有需要的路径,都使用相对路径
	define("BROPHP_PATH", str_replace("\\", "/", dirname(__FILE__)).'/');     //BroPHP框架的路径

	define("APP_PATH", rtrim(APP,'/').'/');            //用户项目的应用路径
	define("PROJECT_PATH", dirname(BROPHP_PATH).'/');  //项目的根路径,也就是框架所在的目录
	define("TMPPATH", str_replace(array(".", "/"), "_", ltrim($_SERVER["SCRIPT_NAME"], '/'))."/");
	
	//包含系统配置文件
	$config=PROJECT_PATH."config.inc.php";
	if(file_exists($config)){
		include $config;
	}
	//设置Debug模式
	if(defined("DEBUG") && DEBUG==1){
		$GLOBALS["debug"]=1;                 //初例化开启debug
		error_reporting(E_ALL ^ E_NOTICE);   //输出除了注意的所有错误报告
		include BROPHP_PATH."bases/debug.class.php";  //包含debug类
		Debug::start();                               //开启脚本计算时间
		set_error_handler(array("Debug", 'Catcher')); //设置捕获系统异常
	}else{
		ini_set('display_errors', 'Off'); 		//屏蔽错误输出
		ini_set('log_errors', 'On');             	//开启错误日志,将错误报告写入到日志中
		ini_set('error_log', PROJECT_PATH.'runtime/error_log'); //指定错误日志文件

	}
	//包含框架中的函数库文件
	include BROPHP_PATH.'commons/functions.inc.php';
	

	//包含全局的函数库文件,用户可以自己定义函数在这个文件中
	$funfile=PROJECT_PATH."commons/functions.inc.php";
	if(file_exists($funfile))
		include $funfile;

	
	//设置包含目录(类所在的全部目录),  PATH_SEPARATOR 分隔符号 Linux(:) Windows(;)
	$include_path=get_include_path();                         //原基目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."bases/";       //框架中基类所在的目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."classes/" ;    //框架中扩展类的目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."libs/" ;       //模板Smarty所在的目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."libs/sysplugins/";
	$include_path.=PATH_SEPARATOR.PROJECT_PATH."classes/";    //项目中用的到的工具类
	$controlerpath=PROJECT_PATH."runtime/controls/".TMPPATH;  //生成控制器所在的路径
	$include_path.=PATH_SEPARATOR.$controlerpath;             //当前应用的控制类所在的目录 

	//设置include包含文件所在的所有目录	
	set_include_path($include_path);

	//自动加载类 	
	function __autoload($className){
		if($className=="memcache"){        //如果是系统的Memcache类则不包含
			return;
		}else if($className=="Smarty"){    //如果类名是Smarty类,则直接包含
			include "Smarty.class.php";
		}elseif(file_exists(BROPHP_PATH."libs/sysplugins/".strtolower($className).".php")){
			//判断是否是Smarty3内部类,若是就导入
			include strtolower($className).".php";	
		}else{                             //如果是其他类,将类名转为小写
			include strtolower($className).".class.php";	
		}
		Debug::addmsg("<b> $className </b>类", 1);  //在debug中显示自动包含的类
	}

	//判断是否开启了页面静态化缓存
	if(CSTART==0){
		Debug::addmsg("<font color='red'>没有开启页面缓存!</font>(但可以使用)"); 
	}else{
		Debug::addmsg("开启页面缓存,实现页面静态化!"); 
	}
	
	//启用memcache缓存
	if(!empty($memServers)){
		//判断memcache扩展是否安装
		if(extension_loaded("memcache")){
			$mem=new MemcacheModel($memServers);
			//判断Memcache服务器是否有异常
			if(!$mem->mem_connect_error()){
				Debug::addmsg("<font color='red'>连接memcache服务器失败,请检查!</font>"); //debug
			}else{
				define("USEMEM",true);
				Debug::addmsg("启用了Memcache");
			}
		}else{
			Debug::addmsg("<font color='red'>PHP没有安装memcache扩展模块,请先安装!</font>"); //debug
		}	
	}else{
		Debug::addmsg("<font color='red'>没有使用Memcache</font>(为程序的运行速度,建议使用Memcache)");  //debug
	}

	//如果Memcach开启,设置将Session信息保存在Memcache服务器中
	if(defined("USEMEM")){
		MemSession::start($mem->getMem());
		Debug::addmsg("开启会话Session (使用Memcache保存会话信息)"); //debug

	}else{
		session_start();
		Debug::addmsg("<font color='red'>开启会话Session </font>(但没有使用Memcache,开启Memcache后自动使用)"); //debug
	}
	Debug::addmsg("会话ID:".session_id());
	
	Structure::create();   //初使化时,创建项目的目录结构
	Prourl::parseUrl();    //解析处理URL 

	//模板文件中所有要的路径,html\css\javascript\image\link等中用到的路径,从WEB服务器的文档根开始

	
	//$spath=rtrim(substr(dirname(str_replace("\\", '/', dirname(__FILE__))), strlen(rtrim(dirname(__FILE__),"/\\"))), '/\\');
	$spath=rtrim(substr(dirname(str_replace("\\", '/', dirname(__FILE__))), strlen(rtrim($_SERVER["DOCUMENT_ROOT"],"/\\"))), '/\\');
	$GLOBALS["root"]=$spath.'/'; //Web服务器根到项目的根
	$GLOBALS["public"]=$GLOBALS["root"].'public/';        //项目的全局资源目录
	$GLOBALS["res"]=rtrim(dirname($_SERVER["SCRIPT_NAME"]),"/\\").'/'.ltrim(APP_PATH, './')."views/".TPLSTYLE."/resource/"; //当前应用模板的资源

	$GLOBALS["app"]=$_SERVER["SCRIPT_NAME"].'/';           	//当前应用脚本文件
	$GLOBALS["url"]=$GLOBALS["app"].$_GET["m"].'/';       //访问到当前模块

	define("B_ROOT", rtrim($GLOBALS["root"], '/'));
	define("B_PUBLIC", rtrim($GLOBALS["public"], '/'));
	define("B_APP", rtrim($GLOBALS["app"], '/'));
	define("B_URL", rtrim($GLOBALS["url"], '/'));
	define("B_RES", rtrim($GLOBALS["res"], '/'));


	//控制器类所在的路径
	$srccontrolerfile=APP_PATH."controls/".strtolower($_GET["m"]).".class.php";

	Debug::addmsg("当前访问的控制器类在项目应用目录下的: <b>$srccontrolerfile</b> 文件!");
	//控制器类的创建
	if(file_exists($srccontrolerfile)){
		Structure::commoncontroler(APP_PATH."controls/",$controlerpath);
		Structure::controler($srccontrolerfile, $controlerpath, $_GET["m"]); 

		$className=ucfirst($_GET["m"])."Action";
		
		$controler=new $className();
		$controler->run();

	}else{
		Debug::addmsg("<font color='red'>对不起!你访问的模块不存在,应该在".APP_PATH."controls目录下创建文件名为".strtolower($_GET["m"]).".class.php的文件,声明一个类名为".ucfirst($_GET["m"])."的类!</font>");
		
	}
	//设置输出Debug模式的信息
	if(defined("DEBUG") && DEBUG==1 && $GLOBALS["debug"]==1){
		Debug::stop();
		echo Debug::message();
	}



可以分析得知,是通过/index/index/的形式,来调用相应的代码。所以我们的路由解析就算差不多了。

<?php

	class Prourl {
		/**
		 * URL路由,转为PATHINFO的格式
		 */ 
		static function parseUrl(){
			if (isset($_SERVER['PATH_INFO'])){
      			 	//获取 pathinfo
				$pathinfo = explode('/', trim($_SERVER['PATH_INFO'], "/"));
			
       				// 获取 control
       				$_GET['m'] = (!empty($pathinfo[0]) ? $pathinfo[0] : 'index');

       				array_shift($pathinfo); //将数组开头的单元移出数组 
      				
			       	// 获取 action
       				$_GET['a'] = (!empty($pathinfo[0]) ? $pathinfo[0] : 'index');
				array_shift($pathinfo); //再将将数组开头的单元移出数组 

				for($i=0; $i<count($pathinfo); $i+=2){
					$_GET[$pathinfo[$i]]=$pathinfo[$i+1];
				}
			
			}else{	
				$_GET["m"]= (!empty($_GET['m']) ? $_GET['m']: 'index');    //默认是index模块
				$_GET["a"]= (!empty($_GET['a']) ? $_GET['a'] : 'index');   //默认是index动作
	
				if($_SERVER["QUERY_STRING"]){
					$m=$_GET["m"];
					unset($_GET["m"]);  //去除数组中的m
					$a=$_GET["a"];
					unset($_GET["a"]);  //去除数组中的a
					$query=http_build_query($_GET);   //形成0=foo&1=bar&2=baz&3=boom&cow=milk格式
					//组成新的URL
					$url=$_SERVER["SCRIPT_NAME"]."/{$m}/{$a}/".str_replace(array("&","="), "/", $query);
					header("Location:".$url);
				}	
			}
		}
	}

漏洞分析

任意文件删除

通过rips发现,在admin的controls中,有个flink.class.php文件。其中update存在unlink导致的任意文件删除。
在这里插入图片描述
我们定位到指定函数中查看, 这里从logo函数中直接传入文件名字,这里这需要logoc参数存在即可执行unlink函数。所以我们这里直接构造payload。

	function update(){
 			$flink = D('flink');
			if(isset($_POST['logoc'])){
				$logo = $flink->downlogo($_POST['logoc']);
				$srclogo = PROJECT_PATH."public/uploads/logos/".$_POST["logo"];
				if(file_exists($srclogo))
					unlink($srclogo);
			}else{
				$logo = $_POST["logo"];
			}
			if($logo){
				$_POST["logo"] = $logo;
				if($flink->update($_POST,1,1)){
					$this->redirect("index");
				}else{
					$mess = $flink->getMsg();
					if($mess == "")
						$mess = "您未做任何修改";
					$this->mess($mess,false);
					$this->assign("post",$_POST);
				}
			}else{
				$this->mess("LOGO下载失败,请检查URL地址是否正确",false);
				$this->assign("post",$_POST);
			}
			$this->display("mod"); 
		}

在这里插入图片描述

在这里插入图片描述

任意文件写入

在admin\models\flink.class.php文件中,这里file_put_contents函数的$data参数直接从$logour获取而来。file_get_content可以从远程主机获取字符串。$location的位置可以直接访问执行。

		function downlogo($logourl){
			$url = parse_url($logourl); //這裡整理為可用的url
			$logoname = str_replace(".","_",$url['host']).".".array_pop(explode(".",basename($logourl)));
			$path = PROJECT_PATH."public/uploads/logos/";
			if(!file_exists($path)){
				mkdir($path);
			}
			$location = $path.$logoname;
			$data = file_get_contents($logourl);   //file_get_contents函數可從網絡中獲取文件。
			if(strlen($data) > 0){
				file_put_contents($location,$data);    //location路徑是public/uploads/logos中,可以直接訪問。
				return $logoname;
			}else{
				return false;
			}
		}
	}

于是搜索哪里调用了该函数。发现也是在flink类里的insert中。

function insert(){
			$flink = D('flink');
			$_POST['dtime'] = time();
			$logo = $flink->downlogo($_POST['logo']);//下载LOGO并返回LOGO名称
			if($logo){
				$_POST['logo'] = $logo;
				if($flink->insert($_POST,1,1)){
					$this->mess('友情链接添加成功',true);
				}else{
					$this->mess($flink->getMsg(),false);
					$this->assign('post',$_POST);
				}
			}else{
				$this->mess('LOGO下载失败,请检查URL地址是否正确',false);
				$this->assign('post',$_POST);
			}
			$this->display('add');
		}

构造payload使用。
在这里插入图片描述
在这里插入图片描述

任意文件写入

继续在项目中搜索file_put_contentsh函数,发现在baseset.class.php文件中的writeindex函数汇总使用该函数。直接修改/index.php页面的TPLSTYLE和CSTART这两个参数。

static function writeindex($style,$start){
			$file=PROJECT_PATH."index.php";
			$content=file_get_contents($file);
			$reg[]="/define\(\"TPLSTYLE\".+?;/i";
			$reg[]="/define\(\"CSTART\".+?;/i";
			$rep[]="define(\"TPLSTYLE\",\"{$style}\");";
			$rep[]="define(\"CSTART\",\"{$start}\");";
			file_put_contents($file, preg_replace($reg, $rep, $content));
		}

我们全局搜索哪初使用了writeindex函数。发现在writeConfig函数中,使用$post参数传入,于是继续全局搜索writeConfig函数调用情况。
在这里插入图片描述

在admin/controls/base.class.php文件中使用了writeConfig。分析下参数传递链,是通过$_POST->($post[‘appStyle’],$post[‘cstart’])->($style,$start)这样的形式传递的。所以我们构造payload,传递appStyle和cstart这两个参数。使得恶意代码执行。
在这里插入图片描述
因此成功执行代码。
在这里插入图片描述
在这里插入图片描述
写入一句话木马,然后菜刀连接。
在这里插入图片描述
在这里插入图片描述

资料

YIXUNCMS2.0:
链接:https://pan.baidu.com/s/17G5CcxVkcwrUq65Zk2JqVQ 密码:ydwg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YIXUNCMS(易迅企业网站建设系统) v2.0.3    简约版系统更新日志 20150709更新 1、YIXUNCMS简约时尚版发布 2、导航栏目调整 3、新增图集、相册功能模块 4、修复用户组管理BUG YIXUNCMS2.0简约版是易迅BS软件工作室专门为中小型企业网站建设开发的一套便捷CMS管理系统完全开源免费。YIXUNCMS2.0系统具有操作简单、安装方便、管理轻松等诸多优点,即使您没有网站布署经验也可轻松使用。   系统基本特点: 1、采用目前流行的PHP语言编写,底层采用超轻量级框架作为系统支撑; 2、页面布局使用DIV CSS技术,遵循WEB标准,及大提高页面的浏览速度; 3、使用应用广泛的SMARTY模板引擎,页面高速缓存,提高网站运行速度,降低大访问量对服务器造成的压力; 4、采用MVC开发模式,搭配多套不同风格模板,使网站改版更加轻松; 5、PHP5完全的OOP设计思想,支持无限分类; 6、前台交互采用AJAX无刷新技术,交互体验更友好; 7、操作页面友好提示,随时了解自己的操作动态; 8、安装布署及为简单,瞬间搭建好属于您的企业网站;   YIXUNCMS2.0简约版的改进 1、去掉了文章评论、在线调查、会员注册、资源管理等普通企业较为不常用的功能; 2、完善了基本设置的管理,如版权信息、ICP备案号等; 3、增加页面导航管理,可自主后台管理导航栏目、目标方式、链接、排序; 4、改变了YIXUNCMS1.0的留言及管理方式,留言内容的查看及管理由前端移入后台; 5、增加前端焦点图管理功能,解决了YIXUNCMS1.0焦点图无法更换的问题; 6、前端应页重新进行了简约式的设计并采用CSS DIV布局; 7、根据百度基础SEO标准,我们加入了必要的标签进行了完善;网站的文章及展示内容页我们添加了分享功能以便适应现代互联网多元化的浏览需求; 8、一级导航条增加了位置固定功能,方便浏览者在阅读较长内容时随时切换浏览页面; 9、较YIXUNCMS1.0,2.0简约版增加了站内搜索功能,方便浏览者在众多文章中进行关键字查询; 10、YIXUNCMS2.0简约版新增了WAP(移动端)应用,并使用浏览器自动识别机制,使网站能适应用于不周的设备及浏览器; 易迅BS软件工作室承诺:系统功能完全由易迅BS工作室亲自编写、绝非二次开发、绝无一行废代码。       相关阅读 同类推荐:cms系统
YIXUNCMS企业网站建设2015.10.28更新日志 1.新增文章栏目图片设置; 2.修改首页文章调用控制器; 3.首页文章栏目布局微调 4.更改CSS部分样式文件; 5.调整留页板页面布局; YIXUNCMS企业网站建设系统系统介绍: YIXUNCMS网站建设系统是由易迅软件工作室专为中小型企业开发的一套展示类网站系统,采用目前流行的PHP语言并搭配性能稳定的MYSQL数据库,前后推出了“YIXUNCMS标准版”、“YIXUNCMS简约版”、“YIXUNCMS时尚版”、“YIXUNCMS增强版(也称强化版)”、“YIXUNCMS企业营销版”为给企业提供更加适合的系统,我们不断对系统进行性能升级及功能改进,使其能够加迎合企业的需求。 YIXUNCMS企业网站建设系统特点: 1、采用目前流行的PHP语言编写,底层采用超轻量级框架作为系统支撑; 2、页面布局使用DIV CSS技术,遵循WEB标准,及大提高页面的浏览速度; 3、使用应用广泛的SMARTY模板引擎,页面高速缓存,提高网站运行速度,降低大访问量对服务器造成的压力; 4、采用MVC开发模式,搭配多套不同风格模板,使网站改版更加轻松; 5、PHP5完全的OOP设计思想,支持无限分类; 6、前台交互采用AJAX无刷新技术,交互体验更友好; 7、操作页面友好提示,随时了解自己的操作动态; 8、安装布署及为简单,瞬间搭建好属于您的企业网站; YIXUNCMS企业网站建设系统更新日志 20151018更新 1、增设展示栏目缩图 2、移动站管理权限开放; YIXUNCMS企业网站建设系统注意事项 1、共享版软件只适合试用、本地测试及学习交流使用,不得用于商业用途,如需建立商业站点进行外网投放,请使用购买商业版; 2、您可以在遵守本协议规定和约束的基础上,对软件进行程序修改、页面美化,以适合您网站的需求。 3、您拥有使用本软件构建的网站中收集到的全部会员资料、文章、下载、图片、留言及相关信息的所有权,并独立承担与内容相关的法律义务。 4、未经易迅书面许可,您不得对本软件进行二次开发发展任何派生版本、修改版本用于重新分发; 5、未商业授权之前,不得将本软件用于商业用途及域名挂靠使用; 6、不得对本软件或与之关联的商业授权进行出租、出售、抵押或发放子授权号; 7、易迅工作室不保证您所下载系统功能的完整性,如需使用完整的功能请您选择授权版 运行环境:Apache PHP MySql PhpMyadmin,本机测试建议安装集成环境 前端架构:HTML CSS DIV JQUERY 程序架构:PHP Mysql YIXUNCMS企业网站建设系统前台页面: YIXUNCMS企业网站建设系统后台管理 默认后台地址:http://您的网址/admin.php 用户名与密码:admin 123456(安装时可设置) 后台页面: 相关阅读 同类推荐:企业网站源码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值