经身份验证的任意文件上传导致远程代码执行 对 Webkul Krayin CRM 2.2.x 中 CVE-2026-38526 的技术分析与受控复现。
CVE-2026-38526 是一个影响 Webkul Krayin CRM 2.2.x 的经身份验证的任意文件上传漏洞。
该易受攻击的功能通过应用程序的 TinyMCE 上传端点暴露:
POST /admin/tinymce/upload
应用程序未充分限制可上传文件的类型。经身份验证的用户可以提交带有服务器端可执行扩展名(例如 .php)的文件。应用程序会存储上传的文件并返回其可访问的 URL。
当部署环境允许从上传位置执行 PHP 时,上传的文件随后可通过 Web 服务器请求,从而在 Web 应用程序进程的上下文中导致远程代码执行。
已发布的 CVE 记录将该漏洞评为 CVSS 3.1:9.9(严重)。
本仓库包含我本人对该漏洞的技术分析与受控复现。
该漏洞已在 CVE-2026-38526 下公开披露。本工作不主张发现了该漏洞。本研究的目的是理解易受攻击的实现、在受控环境中复现利用路径,并考察将文件上传问题转化为远程代码执行的条件。
该漏洞还被用于 Hack The Box GCSB 2026 Nexus 靶机,这为研究该问题提供了实践环境。
产品: Webkul Krayin CRM 受影响版本: 2.2.x 漏洞: 任意文件上传 最终影响: 远程代码执行 身份验证: 必需 攻击向量: 网络 CWE: CWE-434 — 危险类型文件的不受限上传 CVSS: 9.9 严重 CVE: CVE-2026-38526
该易受攻击的功能由以下端点处理:
/admin/tinymce/upload
该端点通过 file 参数接收上传的文件。 相关应用程序逻辑从原始文件名派生存储的文件名,并保留其原始扩展名。

此行为很重要,因为应用程序并非仅仅接受一个上传对象;它保留了攻击者控制的可执行扩展名,并使生成的对象可通过应用程序存储机制访问。
主要问题是对上传文件的服务器端验证不足。
应用程序在构造存储文件名时使用客户端提供的原始扩展名。没有足够严格的允许列表来阻止可执行文件类型进入存储层。
相关流程为

使用生成的文件名并不能解决根本问题。
例如,将 shell.php 改为生成的文件名(如 .php)并不能使上传的文件变得安全,如果服务器继续将 .php 文件解释为可执行的 PHP 代码。
不受限的上传并不自动意味着远程代码执行。
执行路径取决于服务器对上传文件的处理方式。
在易受攻击的部署场景中,攻击链变为

如果上传目录禁用了 PHP 执行,即使底层的任意文件上传弱点仍然存在,也可以阻止直接的 RCE 路径。
wget:
wget https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/upload.py
wget https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/marker.php
curl:
curl -LO https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/upload.py
curl -LO https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/marker.php
2. 将文件放入
poc/
├── upload.py
└── marker.php
3. 创建 Python 环境并安装依赖
python3 -m venv .venv
source .venv/bin/activate
pip install requests
4. 使 PoC 可执行
chmod +x poc/upload.py
6. 运行它
python3 poc/upload.py \
--url http://[Lab_IP:PORT] \
--email [email protected] \
--password 'YOUR_PASSWORD'
该漏洞利用需要一个能够访问易受攻击功能的已认证账户。
概括来说:
最终的执行上下文由底层部署决定。在典型的 Linux 部署中,这可能是 Web 服务器服务账户,例如:
www-data
这并不会自动提供操作系统 root 权限。进一步的影响取决于被攻陷环境的权限和配置。
易受攻击的行为可以归结为三个重要操作。
获取上传的文件
$file = request()->file('file');
应用程序接收客户端提供的文件。
保留客户端控制的扩展名
$filename = md5($file->getClientOriginalName().time())
.'.'.$file->getClientOriginalExtension();
文件名本身被更改,但原始扩展名被保留。 这是一个重要的区别:文件名随机化并不是文件类型验证。
存储并暴露文件
$path = $file->storeAs($this->storagePath, $filename);
return [
'file' => $path,
'file_name' => $file->getClientOriginalName(),
'file_url' => Storage::url($path),
];
应用程序存储该文件并向客户端提供其 URL。
成功利用可使攻击者以 Web 应用程序的权限执行代码。
根据部署情况,这可能允许攻击者:
读取应用程序文件
访问应用程序配置
获取数据库凭据或其他机密信息
修改应用程序数据
部署额外的恶意代码
以被攻陷主机为跳板转向其他可访问的系统
尝试进一步的权限提升
实际影响取决于被攻陷应用程序进程的权限以及底层系统的安全配置。
安全的实现应采用多层防护,而不是依赖单一的扩展名检查。
只应接受明确需要的文件类型。 例如:
.jpg
.jpeg
.png
.gif
.webp
确切的允许列表应反映应用程序的合法需求。
不要仅依赖:
上传的文件应获得由服务器生成的文件名,并且不应保留攻击者可控的可执行扩展名。
应在用于存放用户上传内容的目录中禁用 PHP 及其他服务器端解释器。 即使上传验证控制被绕过,这也能提供额外的安全边界。
在可行的情况下,上传内容应存储在可执行的 Web 根目录之外,并通过受控机制提供访问。
只有真正需要上传功能的已认证用户和角色才应有权访问该端点。
CVE-2026-38526 在本研究之前已公开披露。
本仓库代表我对该漏洞的独立技术分析和受控复现。它不主张原创发现或 CVE 分配。
研究员:Gabriel D. Ishengoma
方向:漏洞研究 / 攻击性安全
CVE-2026-38526 MITRE CVE 记录: https://cve.org/CVERecord?id=CVE-2026-38526
NVD CVE-2026-38526: https://nvd.nist.gov/vuln/detail/CVE-2026-38526
Webkul Krayin CRM 上游源代码: https://github.com/krayin/laravel-crm
CVE-2026-38526 公开安全公告: https://github.com/advisories/GHSA-7xqf-8v3m-6q9w
Hack The Box GCSB 2026 Nexus: https://app.hackthebox.com/machines/Nexus
Krayin CRM 2.2.x 独立技术分析: https://github.com/Ish3ng0m4