跳到主要内容

Nacos 登录异常和异常管理员账号清理

这次遇到的问题是:开发环境 Nacos 原来的账号密码突然登录不上,页面提示“用户名或密码错误”,接口返回 user not found!。一开始很容易以为只是密码被人改了,但实际排查下来,问题更接近一次暴露服务被扫描后的异常账号写入。

这篇记录只保留排查和修复方法,不记录真实公网 IP、真实密码、token、数据库密码等敏感信息。

现象

Nacos 控制台登录失败:

用户名或密码错误

用登录接口测试时,返回:

HTTP/1.1 403
user not found!

开发环境里 Nacos 是 Docker 容器运行,鉴权已开启:

docker ps | grep nacos
ps -ef | grep '[n]acos'

可以看到类似参数:

-Dnacos.standalone=true
-Dnacos.core.auth.enabled=true

先确认 Nacos 用的是哪个用户库

先进入服务器看 Nacos 容器的环境变量和配置。

docker exec nacos sh -lc 'env | sort | grep -Ei "MYSQL|NACOS_AUTH|NACOS_CORE"'
docker exec nacos sh -lc 'grep -nE "db\\.|nacos.core.auth" /home/nacos/conf/application.properties'

这次确认 Nacos 使用的是同机 MySQL 容器里的 nacos_config 库,用户表是:

nacos_config.users
nacos_config.roles
nacos_config.permissions

检查用户和角色:

SELECT username, enabled FROM users ORDER BY username;
SELECT username, role FROM roles ORDER BY username, role;

结果发现除了正常的 nacos,还有多个异常账号,并且有异常账号拥有 ROLE_ADMIN

备份鉴权表

修复前先备份 Nacos 鉴权相关表。

mkdir -p /root/nacos_auth_backup_$(date +%Y%m%d_%H%M%S)

mysqldump nacos_config users roles permissions > nacos_auth_tables.sql

如果 MySQL 跑在 Docker 里,就用容器执行:

docker exec mysql sh -lc 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" nacos_config users roles permissions' > nacos_auth_tables.sql

删除异常账号并还原 nacos 用户

这次保留 nacos 账号,删除异常账号和角色。

START TRANSACTION;

UPDATE users
SET enabled = 1
WHERE username = 'nacos';

DELETE FROM permissions
WHERE role IN (
SELECT role
FROM roles
WHERE username IN (
'hack',
'hacker_admin',
'nv_276a8851',
'nv_54860ba0',
'nv_6eb77951',
'nv_7fbdae4f',
'special'
)
);

DELETE FROM roles
WHERE username IN (
'hack',
'hacker_admin',
'nv_276a8851',
'nv_54860ba0',
'nv_6eb77951',
'nv_7fbdae4f',
'special'
);

DELETE FROM users
WHERE username IN (
'hack',
'hacker_admin',
'nv_276a8851',
'nv_54860ba0',
'nv_6eb77951',
'nv_7fbdae4f',
'special'
);

COMMIT;

修复后应该只剩:

nacos 1
nacos ROLE_ADMIN

BCrypt 的坑

这里踩了一个坑:不能随便用系统工具生成 BCrypt hash 后直接写进 users.password

第一次用了 htpasswd -B 生成 BCrypt,表面上格式也是 $2a$,长度也是 60,但 Nacos 登录仍然返回:

user not found!

打开 MySQL general log 临时抓一次登录请求,确认 Nacos 确实在查用户表:

SELECT username,password FROM users WHERE username='nacos';

所以问题不是“查不到用户表”,而是密码 hash 没有被 Nacos 正确校验。最终用 Nacos 容器里自带的 spring-security-crypto 生成 BCrypt hash,再写回 users.password 后登录恢复。

生成方式示例:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class NacosHash {
public static void main(String[] args) {
System.out.print(new BCryptPasswordEncoder().encode(System.getenv("NACOS_RESTORE_PASS")));
}
}

从 Nacos jar 里取对应依赖:

jar xf /home/nacos/target/nacos-server.jar \
BOOT-INF/lib/spring-security-crypto-5.7.10.jar \
BOOT-INF/lib/spring-jcl-5.3.29.jar

再编译运行,把生成的 hash 写回:

UPDATE users
SET password = '<Spring Security 生成的 BCrypt hash>',
enabled = 1
WHERE username = 'nacos';

验证

用登录接口验证:

curl -i -X POST 'http://<nacos-host>:8848/nacos/v1/auth/users/login' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=nacos' \
--data-urlencode 'password=<password>'

成功时会返回:

{
"accessToken": "...",
"tokenTtl": 18000,
"globalAdmin": true,
"username": "nacos"
}

再用 token 读取一个配置,确认权限正常:

curl 'http://<nacos-host>:8848/nacos/v1/cs/configs?dataId=xxx.yaml&group=DEFAULT_GROUP&tenant=xxx&accessToken=xxx'

入侵痕迹

MySQL general log 里看到过来自内网地址的 root 连接,查询内容里出现反连 shell 相关字符串,随后又执行了关闭 general log 的操作。

这说明问题不只是 Nacos 密码错误,而是服务器暴露面已经被扫描或尝试利用。

当时还检查了:

crontab -l
grep -RInE 'bash -i|/dev/tcp|curl|wget' /etc/crontab /etc/cron.d /var/spool/cron 2>/dev/null
ss -antp | grep -E ':8848|:3306'

没有发现 cron 里已经落地反连任务,但 MySQL 和 Nacos 端口仍然公网监听,这个风险必须处理。

加固清单

这类问题修完登录只是第一步,后面更重要的是收口暴露面。

必须做:

  • Nacos 8848 不要直接公网开放,只允许 VPN、内网或固定办公 IP。
  • MySQL 3306 不要直接公网开放,只允许应用服务器或堡垒机访问。
  • 轮换 Nacos 登录密码。
  • 轮换 Nacos auth token。
  • 轮换 MySQL root 密码。
  • 删除所有异常 Nacos 账号和角色。
  • 检查 usersrolespermissions 是否又被写入异常数据。
  • 打开必要的访问日志,但不要长期开启 MySQL general log。

可以定期检查:

SELECT username, enabled FROM nacos_config.users ORDER BY username;
SELECT username, role FROM nacos_config.roles ORDER BY username, role;

总结

Nacos 登录提示 user not found! 不一定是真的没有用户,也可能是密码 hash 校验失败后的泛化提示。遇到这类问题时,不要只在控制台反复试密码,应该先确认 Nacos 实际连接的数据库,再检查 usersrolespermissions

这次的关键经验有三个:

  1. 修复前先备份鉴权表。
  2. Nacos 密码 hash 用它自身依赖的 Spring Security BCrypt 生成,不要随便混用工具。
  3. 发现异常管理员账号后,要把问题当安全事件处理,重点收口 88483306