Laranode服务器管理面板爆出任意文件写入漏洞(POC已公开)"

admin 2026-10-16 14:04:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

Laranode服务器管理面板爆出任意文件写入漏洞(POC已公开)

YGnight
YGnight

night安全

2026年10月11日 10:08
四川

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

一、漏洞描述

Laranode 是装在服务器上的虚拟主机管理面板,Laravel 写的,一套面板管着好几个租户的站点和数据库。

面板里带了个文件管理器,租户登录后能在自己的家目录里传文件、改内容。

1.2 及更早版本里,上传接口把文件写到哪个目录,是由请求里的一个字段定的。

这个字段没有被清理。

里面带 ../ 的话,会原样进到最后那次字符串拼接。

于是普通租户账号能把文件落到别的租户家目录下面,连文件内容一起。

编号 CVE-2026-100520,厂商公告 GHSA-34h2-2696-vfvr,归类 CWE-22。

CVSS 3.1 打分 8.8,向量 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H,三项影响都记 High。

CVSS 4.0 打分 8.7,向量 AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H。

两份都由 VulnCheck 给出。NVD 那条记录状态是 Deferred,没自己评分。

受影响区间从 0 到 1.2,1.2.1 修掉。

触发要一个能登录面板的普通租户账号。管理员权限不需要,用户交互也不需要。

能写成功还靠一层部署状态。安装脚本会把面板进程加进每个租户的组,租户家目录对它是组可读写的。

当时挡在租户与租户之间的,就是应用层那段路径处理。

文件落到别人的站点根目录之后,剩下交给 Web 服务器。请求到那个文件就会被解析运行,进程权限沿用的是那个租户的系统用户。

公开的验证脚本已经放出,一个 poc.py。

时间上,修复代码 2026 年 9 月 21 日合并,CVE 记录同年 9 月 26 日发布,9 月 30 日最后一次更新。

公开情报里没有观测到在野利用记录。EPSS 对这个编号没有返回数据。

CVE 编号 CVE-2026-100520
公告编号 GHSA-34h2-2696-vfvr
漏洞类型 路径穿越转任意文件写入,CWE-22
影响组件 Laranode 文件管理器的上传动作 app/Actions/Filemanager/UploadFileAction.php,接口 POST /filemanager/upload-file
受影响版本 0 到 1.2,含 1.2
修复版本 1.2.1
触发前提 持有任意一个能登录面板的普通租户账号
利用条件 无需管理员权限,无需用户交互,目标目录对面板进程可写
危害面 跨租户写文件,写进对方站点根目录后可被请求执行,以该租户系统用户身份运行
CVSS 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H,8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H,均由 VulnCheck 给出
在野利用 公开情报中暂无已观测到的在野利用记录

二、漏洞原理

入口挂在 POST /filemanager/upload-file 上,中间件只有 auth 一条。控制器那一层做的是转发,中间没有别的动作。

// routes/web.php v1.2
Route::post('/filemanager/upload-file', [FilemanagerController::class, 'uploadFile'])
    ->middleware(['auth'])->name('filemanager.uploadFile');

// app/Http/Controllers/FilemanagerController.php v1.2
public function uploadFile(UploadFileAction $uploadFile, Request $r)
{
    return $uploadFile->execute($r);
}

处理全落在 execute 里,开头是表单校验。

// app/Actions/Filemanager/UploadFileAction.php v1.2
$r->validate([
    'file' => 'required|file',
    'chunkIndex' => 'required|integer|min:0',
    'totalChunks' => 'required|integer|min:1',
    'originalName' => 'required|string|max:255',
    'path' => 'required|string',
]);

path 这一项挂了两条规则,required 管有没有送过来,string 管是不是字符串。

字符内容一概不管,斜杠、点、长度都没设限。

校验过了就拼路径。

$file = $r->file('file');

$path = '/home/' . $r->user()->systemUsername . '/' . $r->path;

File::append($path . '/' . $r->originalName, $file->get());

落点由三段字符串拼出来,中间不做任何处理。

第一段是 /home/ 加自己的系统用户名,后两段是这次请求里的 path 和 originalName。

后两段之间没有 basename 比对,没有过滤,拼好的结果也没拿回去跟家目录对一次。

拼好的字符串直接进了 File::append。Laravel 这个门面最后落到 PHP 的 file\_put\_contents,路径里那两个点由内核处理,先退一层,再往下走。

本机用 PHP 7.0.9 复算了这次拼接,下面是从点开始的字符串处理结果。

$path = '/home/' . 'alice' . '/' . '../bob/public\_html';
$dest = $path . '/' . 'pwn\_12345.php';

// 本机实际输出
// $dest /home/alice/../bob/public\_html/pwn\_12345.php
// basename($dest) pwn\_12345.php
// dirname($dest) /home/alice/../bob/public\_html

PHP 这一层一个字符都没动,两个点完整保留。真正的目录回溯发生在打开文件时,由内核按路径规则处理。

应答里的 toDestination 就是拼好的那个字符串,此时里面已经是别人的家目录。

同一条 path 还被送去了另一处。

上传完要给新文件修属主和权限。面板进程改不了属主,这一步调 sudo 跑 laranode-file-permissions.sh。

// app/Actions/Filemanager/UploadFileAction.php v1.2 写入之后紧跟的一步
(new EnsurePermissionsAction)->execute($r->path . '/' . $r->originalName, $r->user()->systemUsername);

// app/Actions/Filemanager/EnsurePermissionsAction.php v1.2
Process::run([
    'sudo',
    config('laranode.laranode\_bin\_path') . '/laranode-file-permissions.sh',
    $path,
    $systemUser,
]);

送过去的还是那个带 ../ 的值。越界的就不止写文件这一件事。

那一步脚本是 root 执行的。属主能被改到任意一个写得进去的目标上,权限也一样。

文件写完,后半段就跟文件管理器没关系了。落进 public\_html 的 PHP 文件,被 HTTP 请求到会被 Web 服务器交给 PHP 解析,进程权限沿用那个租户的系统用户。

厂商公告把这里的问题归成两类。另一类是其他操作会跟着符号链接走,编号 CWE-59,1.2.1 一并处理。本篇只跟着上传这一条。

1.2.1 的改法没停在加一层过滤。文件名先被单独约束住了。

// app/Actions/Filemanager/UploadFileAction.php v1.2.1
$originalName = str\_replace('\\', '/', $r->string('originalName')->toString());

if (basename($originalName) !== $originalName || in\_array($originalName, ['.', '..'], true)) {
    return response()->json(['error' => 'Invalid upload file name'], 422);
}

反斜杠先换成斜杠,再拿 basename 比一遍。两边不一致说明带了路径成分,直接 422 挡回去。单独的点与两个点也在黑名单里。

相对的那一段也会先过一遍规整,/home 前缀不再由这一步自己拼。

$relativePath = (new WhitespacePathNormalizer)
    ->normalizePath($r->path . '/' . $originalName);

SafeFileProcess::run(
    'append',
    $homedir,
    [$relativePath, $r->integer('chunkIndex') === 0 ? 'reset' : 'continue'],
    $file->get(),
    $r->user()->systemUsername,
    config('laranode.laranode\_bin\_path'),
);

真正兜住边界的是里面那个辅助脚本,一个 Python 文件 app/Filesystem/safe\_file.py。

def split\_path(path):
    if not path or path.startswith('/') or '\x00' in path:
        fail('Invalid relative path')
    parts = path.split('/')
    if any(part in ('', '.', '..') for part in parts):
        fail('Invalid relative path')
    return parts

def open\_parent(root\_fd, path, create, owner):
    parts = split\_path(path)
    current = os.dup(root\_fd)
    for component in parts[:-1]:
        following = os.open(component, os.O\_RDONLY | os.O\_DIRECTORY | os.O\_NOFOLLOW, dir\_fd=current)
        ...
    return current, parts[-1]

它从家目录取一个描述符,往下的每一级目录都用 O\_NOFOLLOW 打开,锚点始终是那个描述符。

绝对路径、空段、单独一个点、两个点,在 split\_path 这一段就结束了。中间某一级被换成符号链接,os.open 会带上 O\_NOFOLLOW 直接报错。

写入也不再对着目标路径直接打开。

handle = os.open(
    temporary,
    os.O\_WRONLY | os.O\_CREAT | os.O\_EXCL | os.O\_NOFOLLOW,
    0o600,
    dir\_fd=parent,
)
write\_input(handle, source)
os.fchmod(handle, mode)
os.fchown(handle, uid\_gid[0], uid\_gid[1])
os.fsync(handle)
os.rename(temporary, name, src\_dir\_fd=parent, dst\_dir\_fd=parent)

内容先写在随机名的临时文件上,权限和属主改完,再由 rename 挪过去,整条路径都挂在家目录那个描述符下面。

绕这一圈的用意是没有间隔。先判断路径、再打开文件,两步之间是有时间差的,那段空档里目录树可以被改掉。描述符锚定加逐级不跟链接,是把越界变成做不到,而不是检查出来。

这一版还动了两处跟权限有关的东西。sudo 规则从目录通配改成了脚本白名单,面板自己的目录树不再对管理进程组可写。

三、修复建议

升到 1.2.1。

近期值得重点关注的漏洞预警

【紧急漏洞预警】nacos爆出权限绕过漏洞,可以创建管理员账户,经过分析有点出处(已复现,exp脚本已编写)

PostgreSQL爆出远程代码执行漏洞(POC已公开)

【漏洞预警】Atlassian八款产品爆任意文件读取漏洞(附POC)

【漏洞预警】Joomla视频画廊扩展存在SQL注入漏洞(POC已公开)

【漏洞预警】Roundcube网页邮件客户端存在SQL注入漏洞(附POC)

WordPress页面模板存在文件包含漏洞(POC已公开)CVE-2026-87902

WordPress插件Forminator未认证短代码执行漏洞(poc已公开)CVE-2026-92229

WordPress插件Authorizer存在权限提升漏洞(POC已公开)CVE-2026-81294

WordPress插件MStoreAPI存在认证绕过漏洞(POC已公开)CVE-2026-13447

CakePHP爆出SQL注入漏洞(POC已公开)CVE-2026-77635

Node.js模块proxy-addr爆出严重漏洞CVE-2026-90711

Langflow爆出代码执行漏洞CVE-2026-17633  (POC已公开)

Apache CVE-2026-42536,补它只用一行,洞龄十四年

【紧急】搜狗输入法爆出远程代码执行漏洞CVE-2026-51990  ,已被在野利用

【紧急】无需登录就能获取 GitLab 的任意文件数据(附POC)

【紧急】JumpServer堡垒机被公布Access Key泄露漏洞,可以实现提权

Spring Cloud Azure公布严重漏洞 无需任何权限即可取得登录会话

【漏洞POC已公开】Linux RDS 爆出提权漏洞 一块内存放两次,root就到手了

Tenda光猫爆出严重漏洞,目前无补丁(POC已公布

13 行补丁,堵住Linux能拿 root 的内核洞(EXP已公开)

48 字节,换走一台 Windows 的 SYSTEM(CVE-2026-62735漏洞POC已公开)

【漏洞预警】linux删个网桥就能提权root?目前没有补丁(POC已公开)

【漏洞预警】Linux三年前补上的洞,又一次被挖开了

【情报】支付宝8.2亿数据泄露?给同事说一声,别自己吓自己

【漏洞预警】自己注册个号,就能搬空别人的 Magento 订单和支付卡(POC已公开)

【漏洞预警】Next.js 爆出新漏洞,不用登录实现命令执行(POC已公开)

【漏洞补丁绕过预警】Redis CVE-2026-23479变种高危漏洞,EXP已公开

【漏洞补丁绕过】超 30 万 WordPress 站点受影响,Forminator 文件上传漏洞(附POC)

【漏洞预警】Exchange爆出RCE漏洞,利用Exchange 帮另一台 Exchange 开门(POC已公开)

【漏洞预警】不用登录,一个请求就能让 GeoServer 乖乖执行命令(POC已公开)

【漏洞预警】Keycloak不登录就能接管任意账户,双重验证也拦不住

【漏洞预警】 8月WebLogic公布了9个漏洞,有一个需要重点关注

【漏洞预警】近期MongoDB 公布了5个漏洞,最严重的一个可以不认证、远程就能拿下你电脑

【0DAY漏洞】 全球5G手机芯片厂商之一‌的紫光展锐SOC存在RCE漏洞,影响数十家手机厂商,还未发布补丁

【漏洞告警】安卓 14 到 16 全中招,通讯录 SQL 注入漏洞正在抄家(POC已公开)

【漏洞预警】紧急排查,SMB服务再曝新漏洞,利用脚本已公开

【漏洞预警】不用输密码,对方已经接管你的Mac:官方补丁公布macOS存在未鉴权RCE漏洞

【0day漏洞预警】MariaDB 13 爆 9.8 分 RCE 链:最低 USAGE 权限就能远程执行命令

VMware 爆 5 个洞,两个 9.8 不用密码就能打穿 vCente


韩国金融业被AI代理连环突破:技术复盘归因之难,与\"线索\"到\"定罪\"的法律距离" 网络安全文章

韩国金融业被AI代理连环突破:技术复盘归因之难,与\"线索\"到\"定罪\"的法律距离"

韩国7家以上金融机构遭AI代理连环攻击,攻击者使用开源框架artex结合大模型自动化渗透,但因将真实个人信息写入提示词而暴露身份。防守方存在对外接口暴露过多、检测延迟等问题。法律上商业报告仅为线索,定罪需完整证据链,强调个人信息保护与AI取证新挑战。
从SIEM走向AI原生SOC:微软ISOC重构安全运营底座" 网络安全文章

从SIEM走向AI原生SOC:微软ISOC重构安全运营底座"

微软推出集成安全运营中心ISOC预览版,将Sentinel的SIEM能力与DefenderXDR合并至统一门户,解决传统SIEM与XDR系统割裂、分析师需反复切换的痛点。ISOC定位为AI智能体安全时代的统一底层平台,让人与智能体共享信号与上下文。建议新客户开展POC测试,存量用户评估迁移路线,并关注定价与数据留存政策。
评论:0   参与:  0