未认证删任意文件:WordPress 插件 CVSS 9.1 可直接接管站点
红队安全圈
红队安全圈
红队安全圈
2026年11月1日 09:02
重庆
去阅读
一个只验 nonce 的文件删除接口,路径直接取请求体,任何访客都能让服务器删掉任意文件;删中 wp-config.php,站点就是别人的了。
WordPress 生态里删文件的洞不算稀奇,稀奇的是这次两处失误叠在一起:权限判断只验 nonce,不管你是谁;删除路径来自请求体,不做任何规范化。结果就是评级里\"需要订阅者权限\"的那一层被彻底抹掉,一条 POST 请求、body 里一个绝对路径,服务器就执行 unlink。这个洞编号 CVE-2026-103882,CVSS 9.1。
01 漏洞速览
漏洞编号CVE-2026-103882(CWE-22)
影响产品Acadlix LMS 插件 ≤ 1.1.9
漏洞类型路径穿越导致任意文件删除
危害等级9.1 严重(CVSS 3.1)
在野利用暂无公开记录
公开 PoC无独立 EXP,路由与源码已公开
攻击前提站点启用该插件,能打开前台页面
影响面PHP 进程有权写的任意文件
02 成因:一句 nonce 校验,一个没过滤的路径
入口是插件前台命名空间下的一条 REST 路由:
POST /wp-json/acadlix/v1/
front-quiz/{quiz\_id}/
post-delete-assessment-file
权限回调全文只有一句,没有角色判断,没有能力检查:
// FrontQuizController.php L807
check\_permission($request) {
return wp\_verify\_nonce(
$request->get\_header(
'X-WP-Nonce'),
'wp\_rest');
}
它只验一个 wp\_rest nonce。问题是这个 nonce 不是秘密:插件在 Manager.php 第 570 行把同一个 nonce 塞进前台 acadlixOptions 对象,输出到每一个前台页面。任何人打开首页、读一下这个对象就拿到了,而 nonce 对未登录访客同样有效。所谓\"需要订阅者权限\"在事实上等于零权限。
第二处失误在处理函数。文件路径完全信任请求体,执行前没有 realpath、没有文件名过滤、没有目录前缀比对:
// 路径直接来自请求体,无校验
$file\_path = $payload
['delete\_file\_data']['file\_path'];
if (file\_exists($file\_path)) {
wp\_delete\_file($file\_path);
}
同一个类里的上传函数老老实实把文件放在 wp-content/uploads/acadlix-assessment,删除逻辑却从没想过\"是不是只该删这里面的文件\"。正常业务场景是考生删掉自己上传的答卷附件,实际能力是删服务器上任何可写文件。
03 影响范围
· 受影响版本:Acadlix LMS ≤ 1.1.9
· 已修复版本:1.2.0(10 月 23 日发布)把 upload 和 delete 两条路由连同处理函数整段删掉,前台只剩读题、交卷、排行榜
· 判断方式:插件目录 acadlix/readme.txt 里的 Version,或后台插件列表版本号
这插件 2026 年才上架,安装量不大,但用途很清楚:在线考试、培训考核、课程售卖。这类站点的共同点是必须对外开放注册和文件上传,本身就在互联网暴露面上。把面收窄到装了插件的教育类站点,剩下的目标反而更值钱,里面通常有题库、学员手机号、付费订单。
04 危害推演:删掉 wp-config 之后
目前没有公开 EXP,但这条链不需要写代码。先读一遍首页,从页面里翻出 acadlixOptions 的 nonce,再构造请求把 file\_path 指向 wp-config.php。WordPress 启动时发现这个文件不存在,会直接跳到安装向导:站点数据库连接信息没了,页面提示重新安装。攻击者此时填自己的库地址,走完安装流程拿到管理员账号,原有的站和库被隔离。
退一步,就算 wp-config 因为权限删不掉,能做的破坏也不少:
· 删 .htaccess:自定义防护规则、伪静态、部分 WAF 规则一并失效
· 删 uploads 下的文件:历史附件、证书、备份包直接消失
· 删某个插件或主题的主文件:站点白屏或 500,形成持久拒绝服务
· 删 advanced-cache.php 之类 drop-in:缓存层崩塌,流量全量打到数据库
能不能删成功,取决于 PHP 进程对目标文件有没有写权限。共享主机上 wp-config.php 属主往往就是 Web 用户,这种环境下基本一次成功。
还要强调一点:这条权限回调是整个前台命名空间共用的。同一个 check\_permission 还守着交卷、保存成绩、查排行榜这些接口。它们没有 9.1 的评级,但同样能被未认证请求直接调用,伪造答题记录、改分、批量拉取学员榜单在理论上都做得到。这一层比删文件更隐蔽,出事之后很难从业务侧发现。
05 检测与排查
先确认版本,装上没有、装的是哪个版本:
cd wp-content/plugins/acadlix
grep -m1 'Version:' acadlix.php
grep -rn 'post-delete' .
第三条有输出、且版本低于 1.2.0,说明危险路由还在包里。接着看访问日志有没有人打过它:
grep -F 'post-delete-assessment' \
/var/log/nginx/access.log
线上无害探测:拿一个绝对不存在的路径试,确认路由是否可达、权限判断是否形同虚设。
1. 首页拿前台 nonce
curl -s https://host/ \
| grep -o '\"nonce\":\"[a-f0-9]\*\"'
2. 指向不存在的文件
CT='Content-Type: application/json'
curl -s -o /dev/null \
-w '%{http\_code}\
' -X POST \
https://host/wp-json/acadlix/v1/ \
front-quiz/1/ \
post-delete-assessment-file \
-H 'X-WP-Nonce: NONCE' \
-H \"$CT\" \
-d '{\"quiz\_id\":1,
\"delete\_file\_data\":
{\"file\_path\":
\"/tmp/acadlix-zz\"}}'
结果这样读:返回 200 且 success 为真,说明路由活着、权限被绕过,只是文件不存在所以没删;返回 401 是 nonce 校验挡住了;返回 404 说明路由已删,1.2.0 及以上就是这种表现。别拿真实文件去验证,删了就是事故。
更快的排法:站点如果开了文件完整性监控,直接查 wp-content 下最近的删除记录,wp-config 消失、.htaccess 消失都是明确异常。
06 修复建议
-
升级到 Acadlix LMS 1.2.0 或更高。官方的做法是直接移除上传和删除功能,升级后前台不再暴露这两条路由。
-
短期升不动,就在网关层拦掉 post-delete-assessment-file 和 upload 这两条路径,一律返 403。
-
自己改代码的话,路径必须做归属校验,只允许删上传目录内的文件:
$base = wp\_upload\_dir()['basedir']
. '/acadlix-assessment';
$real = realpath($file\_path);
if (strpos($real, $base) !== 0) {
return new WP\_Error(
'bad\_path', 'denied',
['status' => 403]);
}
-
权限回调补上能力判断,别只验 nonce。删附件属于改数据,至少要有 edit\_posts 这类能力,或校验附件归属当前用户。
-
兜底加固:wp-config.php 对 Web 用户设只读,打开 DISALLOW\_FILE\_MODS,插件目录设只读;wp-config 和数据库做离线备份,这是被删之后唯一能救回站点的东西。
07 红队视角
这类洞在实战里的价值被低估了。大家注意力都在反序列化和未授权 RCE,但删文件是通往接管最省事的一条捷径:不需要构造 payload,不需要理解业务逻辑,一个路径字符串就够了。门槛低到几乎没有,有前台页面就有 nonce,有 nonce 就能调接口。拿到手先测一个不存在的路径确认可达,再决定动不动手,全程不产生破坏性副作用。
报告口径要注意。这个洞很容易被写成\"任意文件删除,需登录\",因为漏洞描述里带着订阅者权限的字样,实际上 nonce 全站公开,实质是未认证。写报告时把 nonce 的出处点出来,前台每个页面都带、在 Manager.php 第 570 行注入,评审就不会再把它降级。分类落到 CWE-22 路径穿越,比 CWE-862 缺授权更贴,因为两层缺陷里路径校验缺失才是根因。
防守侧其实很好判断:凡是删除、下载、读取接口,只要入参里出现路径,就该问一句它凭什么保证这个路径在自己家目录里。nonce 只是防 CSRF 的,不是身份认证,这个混淆在 WordPress 插件里太常见了。
08 源码与复现资料
https://nvd.nist.gov/vuln/detail/CVE-2026-103882
https://plugins.svn.wordpress.org/acadlix/tags/1.1.8/includes/Common/REST/Front/FrontQuizController.php
https://plugins.svn.wordpress.org/acadlix/tags/1.2.0/includes/Common/REST/Front/FrontQuizController.php
说明:没有公开 EXP。把 1.1.8 和 1.2.0 两个版本的控制器源码并排看,就是最直接的补丁对比,删除路由的位置一眼可见。
下期继续蹲厂商补丁和 PoC 动静,关注后漏洞先知道,修复不踩坑。
— END —
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论