logo NodeSeekbeta

[版本发布] Nezha-zero:哪吒V0的第三方维护版本(已确认不受本次漏洞影响)

12345
  • @Kozccm #37 因为我用着最顺手啊~还有ServerStatus主题非常好用

  • @wujin #39 后面可以加个开关,打开后默认复制出来的安装命令禁用远程执行。不过没有移除的打算,远程ssh在大多数情况下还是利大于弊的。

  • Docker部署的主控端怎么迁移升级

  • 
    
    你好,我对 `nezha-zero` 做了一轮静态审查,项目整体可用性不错,但从生产环境安全、兼容性、安装链路和权限边界角度看,有一些建议可以优化。以下内容不是已验证漏洞通报,而是基于源码和部署方式整理的风险点与改进建议,供参考。
    
    ---
    
    ## 一、优先建议修复的问题
    
    ### 1. 安装脚本供应链风险较高
    
    当前安装方式依赖远程脚本下载执行,脚本内部还会继续下载 release、raw 文件、镜像源等内容,并存在拼接命令执行、临时 sudoers、关闭 SELinux 等行为。
    
    建议:
    
    - 避免使用 `eval` 执行拼接命令。
    - 下载二进制或脚本后增加 `sha256` 校验。
    - 默认不要关闭 SELinux。
    - 不建议写入 `NOPASSWD:ALL`- 如果必须临时修改 sudoers,建议使用 `trap cleanup EXIT` 清理,并用 `visudo -cf` 校验。
    
    建议安装流程:
    
    ```bash
    curl -fsSL "$url" -o "$tmp"
    sha256sum -c checksums.txt
    install -m 0755 "$tmp" /usr/local/bin/nezha-agent
    

    2. 登录 Cookie 建议统一设置 Path 为 /

    部分登录态 Cookie 设置时没有明确指定 Path,浏览器可能会按照当前 URL 路径设置默认作用域,导致登录成功后首页不带 Cookie,出现“登录成功但仍未登录”的问题。

    建议所有登录相关 Cookie 明确设置:

    c.SetCookie(
        singleton.Conf.Site.CookieName,
        token,
        maxAge,
        "/",
        "",
        secure,
        true,
    )
    

    建议统一检查:

    • /auth
    • /oauth2/callback
    • /refresh-token
    • /logout

    3. API Token 不建议明文存储和明文展示

    当前 API Token 如果以明文形式存入数据库,并且列表接口可以返回完整 token,一旦数据库、备份、日志或管理端页面泄露,token 就可以直接被使用。

    建议改成:

    • token 原文只在创建时显示一次。

    • 数据库只保存 token_hash

    • 页面只显示 token 前缀,例如 nz_xxxxxx****

    • 增加 token 权限范围,例如:

      • read
      • server:write
      • monitor:write
      • cron:write
      • token:delete
    • 增加:

      • expires_at
      • last_used_at
      • last_used_ip

    建议表结构字段:

    token_prefix varchar(16)
    token_hash char(64)
    scopes text
    expires_at int
    last_used_at int
    last_used_ip varchar(64)
    

    4. CSRF 逻辑与 V1 API Token 兼容方式建议统一

    文档中兼容:

    Authorization: Bearer <API Key>
    Authorization: <API Key>
    

    但如果 CSRF 跳过逻辑只识别 Bearer ,那么裸 Authorization: <API Key> 可能认证成功,但 POST / DELETE 请求被 CSRF 拦截。

    建议:

    • 认证中间件识别 API Token 成功后设置上下文标记。
    • CSRF 中间件根据认证结果跳过,而不是重复判断 Header 格式。

    示例:

    c.Set("auth_via_api_token", true)
    

    CSRF 中间件:

    if v, ok := c.Get("auth_via_api_token"); ok && v == true {
        c.Next()
        return
    }
    

    5. Cron 删除权限建议单独校验超级管理员

    新增、编辑、手动触发 Cron 有超级管理员限制,但通用删除接口如果没有对 cron 做同级权限检查,可能导致低权限用户或兼容 API Token 删除定时任务。

    建议在 cron 删除分支补充:

    case "cron":
        if mygin.BlockIfNotSuperAdmin(c, false) {
            return
        }
        err = singleton.DB.Delete(&model.Cron{}, "id = ?", id).Error
    

    更理想的方式是废弃通用删除接口,拆成显式路由:

    DELETE /api/server/:id
    DELETE /api/monitor/:id
    DELETE /api/cron/:id
    DELETE /api/notification/:id
    

    每个路由独立做权限判断。


    6. 多处 map 取值建议增加 nil / ok 检查

    一些逻辑中从 singleton.ServerListmonitorIDMap 等 map 取值后直接访问字段,如果 server、monitor 已删除,或者数据不一致,可能触发 panic。

    建议统一写法:

    srv, ok := singleton.ServerList[serverID]
    if !ok || srv == nil {
        c.JSON(http.StatusBadRequest, model.Response{
            Code:    400,
            Message: "server not found",
        })
        return
    }
    

    建议重点检查:

    • 批量修改服务器分组
    • 编辑服务器
    • 服务历史记录列表
    • 监控跳过服务器列表解析
    • 任何 map[id].Field 形式的直接访问

    7. /api/v1/ws/server 建议增加连接限制

    兼容 V1 的 WebSocket 状态接口如果公开访问,匿名用户可以制造大量长连接,占用 goroutine、内存和带宽。

    建议增加:

    • 应用层同 IP WebSocket 数量限制。
    • Nginx / Caddy 层连接数限制。
    • 可选 view password / token 校验。
    • Origin 校验。

    Nginx 示例:

    limit_conn_zone $binary_remote_addr zone=nezha_ws_conn:10m;
    limit_req_zone  $binary_remote_addr zone=nezha_ws_req:10m rate=5r/s;
    
    location /api/v1/ws/server {
        limit_conn nezha_ws_conn 5;
        limit_req zone=nezha_ws_req burst=10 nodelay;
    
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://127.0.0.1:18080;
    }
    

    二、中优先级优化建议

    8. 登录限速不建议使用全局计数器

    如果登录失败计数是全局状态,攻击者可以持续提交错误密码,导致所有管理员无法登录。

    建议改为多维度限速:

    login:fail:ip:<client_ip>
    login:fail:user:<username_hash>
    login:fail:ip_user:<client_ip>:<username_hash>
    

    不要让单个攻击 IP 锁死全站登录入口。


    9. trusted proxies 默认范围建议收紧

    如果默认信任整个私网段,例如:

    10.0.0.0/8
    172.16.0.0/12
    192.168.0.0/16
    

    在 Docker、内网、反代、宝塔环境中,可能导致 X-Forwarded-For 被污染,影响:

    • 登录限速
    • 审计日志
    • ClientIP 判断
    • 自动注册来源判断
    • 风控判断

    建议改为显式配置真实反代 IP:

    trusted_proxies:
      - 127.0.0.1
      - 172.18.0.1
    

    10. OAuth Redirect URL 不建议依赖 Host Header 拼接

    OAuth 回调地址如果根据 HostX-Forwarded-ProtoReferer 动态拼接,在反代配置不严谨时容易出现回调地址错乱。

    建议增加固定配置:

    site:
      public_url: "https://status.example.com"
    

    然后统一使用:

    redirectURL := strings.TrimRight(conf.Site.PublicURL, "/") + "/oauth2/callback"
    

    11. NAT Gateway 建议加强 Host 白名单

    NAT Gateway 依赖 Host Header 匹配转发目标,如果 dashboard 域名和 NAT 域名混用,或者反代没有固定 Host,可能触发非预期转发。

    建议:

    • dashboard 域名和 NAT 域名强制分离。
    • NAT 域名必须显式白名单。
    • 拒绝未知 Host。
    • 拒绝 IP Host。
    • 拒绝 dashboard Host 进入 NAT Gateway。
    • 增加 NAT Gateway 访问日志和限速。

    12. V1 API 列表过滤逻辑建议避免依赖排序

    如果列表数据来自 map 遍历或动态组装,就不能假设 ID 已排序。二分查找可能导致偶发找不到、返回错误对象或重启后结果变化。

    建议改为 map 查询:

    byID := make(map[uint64]T)
    for _, item := range list {
        byID[item.ID] = item
    }
    

    ServerGroup 如果没有稳定 ID,建议使用稳定 tag name 或 hash,而不是临时 slice index。


    13. API 错误建议使用真实 HTTP 状态码

    目前如果接口返回体里是 Code: 400/403/404,但 HTTP 状态仍是 200 OK,会影响 API 客户端、监控、反代和 WAF 判断。

    建议 API 路由使用真实状态码:

    c.JSON(http.StatusBadRequest, ...)
    c.JSON(http.StatusUnauthorized, ...)
    c.JSON(http.StatusForbidden, ...)
    c.JSON(http.StatusNotFound, ...)
    

    页面路由可以继续使用统一错误页,但 API 建议标准化。


    14. 配置文件与环境变量优先级建议明确

    如果当前逻辑是配置文件覆盖环境变量,可能和 Docker / Kubernetes 用户的常见预期相反。

    建议:

    • 文档明确说明优先级。
    • 或改成环境变量覆盖配置文件。
    • 或提供配置项控制行为。

    推荐:

    默认:env 覆盖 file
    可选:allow_file_override_env: true
    

    三、低优先级但建议优化的问题

    15. Docker 镜像建议默认非 root 运行

    建议 Dockerfile 增加非 root 用户和 healthcheck:

    RUN adduser -D -H -u 10001 nezha
    USER 10001:10001
    
    HEALTHCHECK --interval=30s --timeout=5s \
      CMD wget -qO- http://127.0.0.1:18080/ || exit 1
    

    同时建议统一文档中的容器监听端口、compose 映射端口和 EXPOSE 端口,避免用户误解。


    16. 初始化密码建议更强,并减少泄露风险

    如果安装脚本生成并明文输出默认密码,终端日志、堡垒机、宝塔终端记录可能泄露。

    建议:

    • 默认生成 16–24 位随机密码。
    • 只显示一次。
    • 明确提醒用户立即修改。
    • 支持非交互模式下不打印密码。
    • 符合项目自身密码复杂度规则。

    17. template.HTML / safe helper 建议限制使用范围

    如果模板函数提供 safe,未来任何用户可控字段误用 safe 都可能变成 XSS。

    建议:

    • 只允许 CustomCodeCustomCodeDashboard 这类明确字段使用 safe。
    • 服务器名称、备注、标签、通知内容等不要使用 safe。
    • 增加 CSP。
    • 后台提示“自定义代码拥有前端执行权限”。

    18. 公开配置接口建议减少返回字段

    如果公开接口返回 CustomCodeCustomCodeDashboard 等配置,可能泄露统计 ID、内部链接、调试信息或第三方脚本地址。

    建议:

    • 公开接口只返回前端展示必须字段。
    • 后台专用字段拆到 authenticated API。

    四、建议修复顺序

    第一批:稳定性和安全边界

    1. 登录 Cookie Path 全部改成 /
    2. CSRF 与 Authorization raw token 兼容修复
    3. cron 删除权限补超级管理员检查
    4. map 取值和历史记录引用增加 nil / ok 检查
    5. /api/v1/ws/server 增加连接限制和访问控制
    

    第二批:权限和认证体系

    6. API Token 改为 hash 存储
    7. 登录限速改为 per-IP + per-user
    8. OAuth redirect URL 改为固定 public_url
    9. trusted proxies 改为显式配置
    10. 安装脚本移除 eval、默认关闭 SELinux、NOPASSWD 等高风险行为
    

    第三批:工程质量和运维体验

    11. Docker 非 root + healthcheck
    12. API HTTP 状态码规范化
    13. V1 API 列表过滤逻辑修复
    14. safe helper 使用范围收敛
    15. 文档明确配置优先级和端口映射
    

    五、总体评价

    项目功能方向很好,兼容 V0/V1、密码登录、2FA、自动发现等能力都很实用。主要风险不在于单点严重漏洞,而在于:

    一键安装脚本
    兼容旧 API
    公开 WebSocket
    API Token
    Host Header / 反代边界
    NAT Gateway
    权限检查复用
    

    这些能力叠加后,生产环境的安全边界会变得比较松。建议优先收紧安装链路、认证权限、公开接口和反代信任范围,这样项目会更适合长期生产使用。

  • 支持

  • @fiaf5829 #45 前两天没空,今天有空了看了一下,目前:
    1.安装脚本供应链风险较高:在当前部署条件下,自己的服务器安装Agent的情况下,如果直接访问Github都会被供应链影响,那即使增加SHA256校验也一样可以被换掉,先集中精力确保面板本身的安全性更加紧急;
    2.gin 的 SetCookie 内部对空 path 做了兜底:if path == "" { path = "/" }
    ,所以登录 handler 不显式传 path 时,等同于 path=/
    3.API Token 不建议明文存储和明文展示:当前API Token确实是按照明文存储的,但是API Token的权限被设定为几乎只读,和密码登录权限有所差异;密码登录产生的Token确实是明文存储的,这个继承自哪吒原版,已经列入ToDo 准备修改成存储哈希
    4.CSRF 逻辑与 V1 API Token 兼容方式建议统一:列入计划,准备修改
    5.Cron 删除缺超管校验:目前Cron 删除已经需要密码或者Oauth校验,但没有对是否为超级管理员进行校验,已修改
    6.map 取值缺 nil/ok:不影响登录安全,但确实存在,后面会统一修一次
    7./api/v1/ws/server 无连接限制:websocket是每次有新的面板连接的时候增加一个链接,暂时没有打算增加限制,暂不修改
    8.登录限速不建议使用全局计数器:这个是安全性考虑,密码登录其实是做了根据IP/用户名限制的,但是还额外做了一个全局1分钟最多尝试120次/每10秒9次的限制,正常用户登录肯定是没有问题的,如果遭到攻击即使短暂锁死登录也不允许可能的攻击持续尝试密码,是安全性优先的策略,暂不修改
    9.当前信任全私网段是为了兼容反代/容器部署。计划收紧:去掉 10.0.0.0/8,保留 127.0.0.1 和 172.16.0.0/12 覆盖典型反代/Docker 网关场景。
    10.OAuth Redirect URL 不建议依赖 Host Header 拼接:如果不依赖Host拼接,就一定得有一个可信的域名来源,大概率让用户手填,会增加配置难度;因此暂时保留了这样的设置,有好的方案欢迎联系我;
    11.NAT Gateway 建议加强 Host 白名单:同上
    12.V1 API 列表过滤逻辑建议避免依赖排序:确认存在,非安全性问题,已加入Todo
    13.API 错误建议使用真实 HTTP 状态码:历史版本已经定义成这样,担心引入兼容性问题,暂不修改
    14.配置文件与环境变量优先级建议明确:正常部署不会碰到这个问题,继承自哪吒原版,暂不修改
    15.Docker 镜像建议默认非 root 运行:成立,属工程/运维加固,优先级比较低
    16.初始化密码建议更强,并减少泄露风险:计划默认增强初始化密码,且允许初始化时侯直接使用密码激活,不强制OAUTH
    17.template.HTML / safe helper 建议限制使用范围:设计目标就是这么用,暂不修改
    18.公开配置接口建议减少返回字段:V1兼容api使用的,用于渲染前端模板,需要公开。V1兼容api默认关闭需要用户手动打开。

  • 好东西啊 流量统计不准的bug修复了吗

  • @Owen #48 具体是怎么不准啊 告警的上下行流量和嘛

12345

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有61916位seeker

🎉欢迎新用户🎉