Skip to content

安全问题: 【!!!Important!!!】公网登录口令过弱 #40

Description

@neil-wang-global

问题描述

公网访问密码目前采用 8 位纯数字方案,但代理层完全没有对多次尝试的阻拦,导致密码容易被暴力破解。建议立刻修复。

技术细节

密码强度分析

  • 8 位纯数字 = 10^8 种组合 (1 亿)
  • 假设每次尝试 100ms 响应:
    • 10,000 次尝试 = 16.7 分钟
    • 100,000 次尝试 = 2.78 小时
    • 穷举全部 = 1.16 天

代码缺陷位置lib/proxy.mjs 第 155-173 行

  • 密码校验后直接返回登录页,无任何延迟或锁定
  • 没有记录客户端 IP 的尝试次数
  • 没有临时锁定机制
  • 没有验证码或二次验证

当前代码问题

if (submitted === token) {
  // 成功:种 cookie
  res.writeHead(302, { ... });
} else {
  // 失败:直接返回登录页,无限重试 ❌
  res.writeHead(200, { ... });
  res.end(loginPageHtml(true, isPublic));
}

影响范围

  • 🔴 公网场景(cloudflare 隧道):高风险,DNS 可被任意客户端扫描
  • 🟡 局域网场景:中低风险,但仍可被同网段用户破解

建议方案

方案 A:速率限制(推荐,立即可行)

在代理层实现简单的 IP-based 速率限制:

  • 记录客户端 IP 的失败次数(内存 Map)
  • 失败 5 次后,60 秒内拒绝新尝试(返回 429)
  • 成功登录后清空该 IP 的计数

优点:快速实现、防止暴力破解
缺点:公网隧道环境下 IP 都来自 cloudflare 边缘节点,可能需要用 X-Forwarded-For 区分

方案 B:公网自定义密码

允许用户在开启公网时自己指定密码:

  • 支持更长、更强的密码(数字 + 字母)
  • 更新设置页 UI,公网开启时提示输入自定义密码
  • 如果不输入,降级到自动生成的 8 位数字

方案 C:强密码自动生成(长期方案)

  • 改为生成更强的密码:如 12-16 字符,含大小写字母 + 数字 + 符号
  • 保持 8 位数字用于局域网快速输入(手机小屏输入体验)
  • 公网/隧道模式用强密码

其他安全建议

  1. 添加尝试日志:记录失败的登录尝试(便于事后审计)
  2. 密码过期:公网密码每小时自动轮换(现在是重启时轮换)
  3. CAPTCHA:多次失败后要求验证码(防止自动化破解)
  4. 限制并发:限制单个客户端的同时连接数

相关代码文件

  • lib/proxy.mjs - 密码校验逻辑
  • lib/index.js - 密码生成与管理
  • client/ - 设置页 UI(若要支持自定义密码)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions