深入剖析项目结构:system目录功能、路由生成规律及代码审计SQL注入情况

项目结构

深入剖析项目结构:system目录功能、路由生成规律及代码审计SQL注入情况

对代码进行大致结构分析后,得知其主要功能都在 system 目录下。

系统目录下存在 class 文件和 template 文件。其中,template 代表前端部分,而 class 则是后端处理的文件。

[id_766520780]

同时也可以搞清楚路由的生成规律:

http://localhost:8097/index.php ,其中 mod 为 site ,act 为 manager 。do=store&op=display&beid=1

image-20220818155609848

这里的 act 参数所指代的是 system 文件夹之下的某个功能点,do 指的是该功能点之下具体的 PHP 文件,op 表示的是该文件所走的分支。

代码审计sql注入

在store.php中有这么一段话。

 if($operation=='display')
        {
$pindex 等于最大值( )1, intval($_GP['page']));
            $psize = 20;

             
              if (!empty($_GP['sname'])) {
$selectCondition 接着加上了store.sname 像 '%{$_GP['sname']}%' 这样的内容;
            }
            

该功能对应为店铺查询处。

image-20220818162558347

image-20220818162527627

追溯源头发现$_GP

只是对 get 和 post 中的数据进行了数组合并这一操作,然而并没有进行任何过滤的动作。

$_GP = $_CMS =  array();
将数组 $_GET、$_POST 和 $_GP 进行合并操作,合并后的结果赋值给 $_GP 。

sql语句代入为

"SELECT store.* FROM  table('system_store') store where store.`deleted`=0  and store.sname like '3' limit 0,20"

我们将数据直接带入数据库,通过这种方式能够判断出这里存在 sql 注入漏洞。

构造payload如下:

sname=123%' and sleep(5) #

image-20220818163745175

image-20220818164529021

sqlmap也验证成功。

任意文件删除

在database.php下有一个delete分支。

     if($operation=='delete')
 {
   $d = base64_decode($_GP['id']);

    $path = WEB_ROOT . '/config/data_backup/';
  if(is_dir($path . $d)) {
   rmdirs($path . $d);
   message('备份删除成功!', create_url('site', array('act' => 'manager','do' => 'database','op'=>'restore')),'success');
  }
}

从上面的代码能够得知,当$_GP['id']函数接收到前端的文件名参数后,只是将该文件名进行了 base64 解密操作,然后就直接把解密后的文件名拼接到了删除文件的路径中,在此过程中并未进行任何的过滤限制操作,从而导致出现了任意文件删除的漏洞。

同时查看代码目录能够发现,每次进行数据库备份之后,都会在 config/data_backup 数据库当中生成一个具有随机性的文件夹。

image-20220818165510899

但是由于删除代码需要进行判断且必须是目录,所以仅能删除目录以及该目录下的文件。

先去代码目录下去新建一个test文件夹。

image-20220818165734351

构造payload如下:

act=manager 表示动作是 manager。do数据库执行删除操作,其操作对象的 ID 为 Li4vdGVzdA==,对应的 beid 为 1。
ps:Li4vLi4vdGVzdA==为../../test

image-20220818170202137

同时源码目录也没有test文件夹。

任意文件删除2

在 common.inc.php 文件里,存在着一个名为 file_delete 的函数。

function file_delete($file_relative_path) {

 if(empty($file_relative_path)) {
  return true;
 }
 
获取全局系统设置并赋值给 $settings 。
 if(!empty($settings['system_isnetattach']))
  {
    if($settings['system_isnetattach']==1)
  {
  require_once(WEB_ROOT.'/includes/lib/lib_ftp.php');
   $ftp=new baijiacms_ftp();
  if (true === $ftp->connect()) {
   if ($ftp->ftp_delete($settings['system_ftp_ftproot']. $file_relative_path)) {
    return true;
   } else {
    return false;
   }
  } else {
   return false;
  }
 } 
  if($settings['system_isnetattach']==1)
  {
  require_once(WEB_ROOT.'/includes/lib/lib_oss.php');
  $oss=new baijiacms_oss();
使用 $oss 来删除文件,文件的相对路径为 $file_relative_path 。
  return true;
 }
}else
{
  if (is_file(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path)) {
  unlink(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path);
  return true;
 }
 
 }
 return true;
}

关键点在于进入下面的 else 条件,便可进行任意文件删除,只需跳过上面的 if 条件。该 if 条件与一个名为 system_isnetattach 的东西有关。

image-20220818172910073

找了很久都不知道它究竟是什么东西,翻译后叫做附件。看了网上的 wp 后才明白,system_isnetattach 是用来设置图片压缩比例的。

image-20220818173028505

接下来我们进入了 else 环节,这个 else 环节的代码十分清晰,一眼就能看明白。

image-20220818170821451

现在我们要去找到 file_delete 函数被调用的地方。能够发现它是在 system/eshop/core/mobile/util/uploader.php 这个文件里面。

先去源码目录创建一个新的文件test.txt

image-20220818173403709

在 baijiacms-master/system/eshop/core/mobile/util/uploader.php 文件的 upload 分支下利用的参数,其参数名为 file。所以构造的 url 为:8097/index.php,其中 mod 为 mobile,act 为 uploader,op 为 post,do 为 util,m 为 eshop,op 为 remove,file 为../test.txt

删除成功。

image-20220818174034952

我也没搞懂怎么找到这个路由的。

任意命令执行

在 8097/index.php?mod=site&act=weixin&do=setting&beid=1 这个地方,存在一个能够上传微信验证文件的选项。

image-20220818175041589

使用burp可以抓包到里面的路由为

image-20220818175308892

根据对应路由,找到代码是

image-20220818175346691

在数据包里,发现传入的文件参数名称是 weixin_verify_file。

image-20220818175451144

发现在setting文件中有相关描述。

image-20220818175622737

意思大致为:首先判断文件的后缀名是否为 txt 格式。接着,利用 file_save 函数来处理文件,并且在 file_save 函数中,参数 file['name'] 指的就是上传的文件的名字,即 &whoami&.txt。

然后再file_save函数当中,传进来了五个参数

image-20220818180617409

文件的完整路径里面包含了我们上传的文件名,还包含了 whoami,并且包含了.txt 。

其中最为重要的一点是,在该方法里调用了 system 函数,并且会将我们的 file_full_path 参数也一并带进去。而我们的&whoami$.txt 恰好能够通过&(与)的分割方式,来实现命令的执行。

image-20220818180732121

image-20220818181041898任意文件写入

在 system/public/class/web/file.php 这个地方发现了如下分支。

if ($do == 'fetch') {
 $url = trim($_GPC['url']);
获取网络文件并进行上传的操作结果为 $file ,该文件来自 $url 。
 if (is_error($file)) {
  $result['message'] = $file['message'];
  die(json_encode($result));
 }
 
}

其中调用了 fetch_net_file_upload 函数,在这个函数中使用了 file_get_contents 函数来获取文件,然而却没有进行任何过滤。

image-20220818181955379总结

太菜了,后面基本是照着网上师傅的 wp 来做的。不过任意命令执行这个漏洞确实让我开阔了视野。另外,我不知道他们是怎样做到精准找到 php 路由的,实在是太菜了。

你可能想看:
« 上一篇
下一篇 »

相关推荐

php实时推送,php实地培训

2026年10月05日

46阅读

php乱码出现问号的原因,php乱码出现问号的原因有哪些

2026年10月05日

38阅读

php一句话木马,一句话木马ctf

2026年10月05日

39阅读

php获取数组长度,php中如何获取数组的长度

2026年10月05日

43阅读

php面试题库及答案,php程序员面试真题库

2026年10月05日

41阅读

phpcontent-type修改,php源码二次修改需要多少钱

2026年10月05日

38阅读