背景
公司的配置中心使用的是 Apollo,并且为开发人员开了专门的账号,所以开发人员都知晓 Apollo 密码。
由于频繁有开发人员离职,为保证密码的安全性,所以准备定期更新 Apollo 密码。
但因公司有多个 Apollo 实例对应多个环境,频繁手动更新肯定不合适,所以就要研究一下如何通过程序修改密码。
方案
有如下两种方案:
- 在浏览器抓包 Apollo 的修改密码流程,用代码模拟浏览器请求进而通过 HTTP API 修改密码;
- 数据库我们是能够访问的,只要能使用脚本找到 Apollo 密码同等的加密方式生成新密码,通过脚本覆盖数据库的密码签名就行了;
对于第 1 种方案,我观察了下,访问修改密码的接口需要进行用户认证,也就是说必须提前获取到管理员认证 Token 并携带这个 Token 去访问修改密码接口才能够修改成功,也就是说还要去研究下如何获取 Token,太麻烦了,所以我就选了第 2 种。
对于第 2 种方案,我们如何才能够知晓 Apollo 密码的加密方式呢。。当然是看源码,Apollo 是使用 Java 实现,并且已开源在 Github,抓包找到修改密码接口对应的 Controller 如下:
从源码一步步搂进去后发现密码加密使用的是这个类:org.springframework.security.crypto.password.PasswordEncoder
,创建它的实现的代码如下:
即可以看到使用的是 bcrypt
算法,现在就好办了,我只需要找到一个该算法的其它语言实现就行了,Python 和 Go 都行啦。。果然 Python 已有现成的库,直接 pip 即可安装:
$ pip install bcrypt
使用也很简单:
import bcrypt
# 密码
pwd = '123456'
# 加密盐
salt = bcrypt.gensalt(rounds=10)
hashed = bcrypt.hashpw(pwd.encode(), salt)
# 加密密码后的签名
print(hashed)
然而并不顺利,我使用上述代码生成的签名去覆盖 Apollo 数据库密码时,使用该签名对应的密码并不能从 Web 端登入,最后经过 google 发现,与 SpringSecurity bcrypt 对等的加密方式生成盐的时候需要添加额外的前缀参数,修改上述代码为如下:
import bcrypt
# 密码
pwd = '123456'
# 加密盐
salt = bcrypt.gensalt(rounds=10, prefix=b"2a")
hashed = bcrypt.hashpw(pwd.encode(), salt)
# 加密密码后的签名
print(hashed)
# $2a$10$eFEwrwTk842CRfORNMM.OuMBC1LoiKuMpJBlpVnqiG62UQx2zklP6
果然,使用生成的签名覆盖数据库密码签名后,可以正常使用 123456
在 Web 端登入了。
评论区