74cms 最新 getshell 漏洞

admin 2025年2月28日23:00:59评论31 views字数 4089阅读13分37秒阅读模式

 

原文链接:https://xz.aliyun.com/news/16959

作者:1398133550745333

0x1 前言

文章中涉及的敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打码处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行承担。

0x2 环境搭建

首先下载源码,直接官网下就好了

https://www.74cms.com/download/detail/161.html

使用 phpstudy 搭建

74cms 最新 getshell 漏洞

然后配置数据库地址和管理员的密码

安装成功后

74cms 最新 getshell 漏洞

参考http://doc.74cms.com/#/se/quickstart?id=%e5%ae%89%e8%a3%85%e7%a8%8b%e5%ba%8f

0x3 漏洞复现

首先需要我们自己先注册一个企业账号

访问/member/reg/company

74cms 最新 getshell 漏洞

自己先注册一个

然后登录

74cms 最新 getshell 漏洞

然后就是我们的企业 logo

可是这里我们内容可以是 base64 来决定,而且文件类型也是可以的

74cms 最新 getshell 漏洞

然后发送这个 POC 会得到一个路径

{"code":200,"message":"生成成功","data":{"file_id":"5","file_url":"*****/upload/company_logo/******.php"}}

访问即可

74cms 最新 getshell 漏洞
0x4 漏洞分析

首先看到我们的漏洞源头代码

application/v1_0/controller/company/Index.php

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,'生成失败');    }}

而当我们传入 imgBase64=data:image/php;base64,PD9waHAgcGhwaW5mbygpOw==的时候

生成的是一个 php 文件

<?phpphpinfo(); ?>
74cms 最新 getshell 漏洞

会直接写入

不过生成文件名有 time 随机的,还好信息中会返回路径

74cms 最新 getshell 漏洞

但是调用这个方法需要初始化

public function _initialize(){    parent::_initialize();    $this->checkLogin(1);}

跟进 checkLogin 方法

publicfunctioncheckLogin($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);    }if($this->userinfo !== null){$member = model('Member')            ->field(true)            ->where('uid'$this->userinfo->uid)            ->find();if($member===null){$this->ajaxReturn(50002'请先登录');        }else{/**             * 【ID1000788】【bug】后台登录简历日志会记录很多条             * cy 2023-12-23             * 通过缓存进行控制,由于前端同时多条接口请求产生了并发所以导致记录了多次             */$cacheKey = 'member_login_key_' . $member['uid'];$loginCache = cache($cacheKey);if (empty($loginCache) && ($member['last_login_time'] == 0 || strtotime(date('Y-m-d'$member['last_login_time'])) != strtotime('today'))) {$expire = strtotime('tomorrow') - time();cache($cacheKey$member['uid'], ['expire' => $expire                ]);$this->writeMemberActionLog($member['uid'], '登录成功'true);            }        }    }}

这里就需要我们注册一个企业的账号了,也就是我们刚刚那个地方

0x5 漏洞修复
这里没有看原作者怎么修复的,我直接因为很明显的问题就是类型严格限制文件类型
防止文件扩展名伪装

publicfunctionsendCompanyLogo() {$imgBase64 = input('post.imgBase64/s''''trim');$company_id = 100;// 正则检查是否是 Base64 编码的图像数据if (preg_match('/^(data:s*image/(w+);base64,)/'$imgBase64$res)) {// 获取图片类型$type = $res[2];// 图片类型检查:仅允许特定类型的图像(JPEG, PNG, GIF等)$allowedTypes = ['jpeg''jpg''png''gif'];if (!in_array(strtolower($type), $allowedTypes)) {$this->ajaxReturn(400'只允许上传图像文件');return;        }// 图片保存路径$new_file = "upload/company_logo/" . $company_id . '/';if (!file_exists($new_file)) {mkdir($new_file0755true);        }// 图片名字$new_file = $new_file . time() . '.' . $type;// 解码 Base64 并保存图片$decodedImage = base64_decode(str_replace($res[1], ''$imgBase64));// 通过 getimagesize() 函数确认文件是有效图像$imageInfo = getimagesizefromstring($decodedImage);if ($imageInfo === false) {$this->ajaxReturn(400'无效的图像文件');return;        }// 保存文件if (file_put_contents($new_file$decodedImage)) {$id = model('Uploadfile')->insertGetId(['save_path' => substr($new_file6),'platform' => 'default','addtime' => time()            ]);$arr = ['file_id' => $id,'file_url' => config('global_config.sitedomain') . '/' . $new_file            ];$this->ajaxReturn(200'生成成功'$arr);        } else {$this->ajaxReturn(500'生成失败');        }    } else {$this->ajaxReturn(400'无效的文件格式');    }}
这里强行要求是图片格式了,php 就不可以了参考https://github.com/wy876/POC/blob/main/74CMS

0x6

原文始发于微信公众号(神农Sec):74cms 最新 getshell 漏洞

 

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月28日23:00:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   74cms 最新 getshell 漏洞https://cn-sec.com/archives/3780528.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息