密码丢失了怎么办?改写数据库呗

假如我们部署的服务使用时间长了忘记了管理员密码,但具有操作数据库的权限,那可以将数据库down下来,改写密码字段的数据来找回密码。本文介绍一下数据库中的密码存储方式和比对原理:

密码存储原理

数据库中的密码是使用BCrypt哈希函数处理过后才进行存储的。BCrypt是一种密码哈希函数,设计的目标是防范彩虹表攻击。典型的数据库中的密码为以下这个字符串$2b$10$v.8FVedx5g49GaFJEZqz6eP0Nejbkb/QmLbNGRTCe/.iOI6d5z/dC ,可以分为四个部分:

  1. 2b :这个部分表示哈希算法的版本,2b是BCrypt的一个版本。

  2. 10 :这个部分是"cost factor",也就是计算哈希值的消耗度。值越大,计算哈希值需要的时间就越长,存储的哈希值就越难破解;

  3. v.8FVedx5g49GaFJEZqz6e :这个部分是盐值(Salt),它是一个随机值,用于和密码一起哈希,以防止两个相同的密码产生相同的哈希值。

  4. P0Nejbkb/QmLbNGRTCe/.iOI6d5z/dC :这个部分就是哈希过的密码。

如何验证密码

在验证用户密码时,你需要取出盐值和消耗度,然后使用同样的参数和用户输入的密码一起计算哈希值,如果计算出的哈希值和存储的哈希值相同,那么密码就是正确的。以下是一个示例代码,在忘记数据库密码时可以使用手动生成的密码改写数据库:

import bcrypt
# 输入的密码
password = "passwd".encode('utf-8')
# 生成盐值
# salt = bcrypt.gensalt()
salt = "$2b$10$v.8FVedx5g49GaFJEZqz6e".encode('utf-8')
# 哈希密码
hashed_password = bcrypt.hashpw(password, salt)
print(hashed_password)
# 密码验证
if bcrypt.checkpw(password, hashed_password):
    print("密码正确")
else:
    print("密码错误")

以上代码打印输入如下:

b'$2b$10$v.8FVedx5g49GaFJEZqz6eP0Nejbkb/QmLbNGRTCe/.iOI6d5z/dC'
密码正确

更改数据库密码

将数据库down下来,使用navicat等软件,打开数据库直接改写存储用户名和密码表中的密码字段为上述代码hashed_password中的字符串即可将密码重置为"passwd"。

13 Likes

学习技术贴了,感谢佬友

话说别人的数据库密码忘了,也能用此方法找回吗:-D

5 Likes

技术贴,点赞

3 Likes

找回是不行的,这只是修改。

6 Likes

好东西

2 Likes

ALTER USER 不香

5 Likes

BCrypt 的密码和用户的其它信息没有关联,也就是说可以把已知密码用户的密码的密文更新到忘记密码的用户上,用已知的密码登录后用系统的更改密码就可以了

2 Likes

可以找回的,
https://github.com/HyperSine/how-does-navicat-encrypt-password
看这里,在导出的配置文件中找出密码,然后直接解密就行

1 Like

那BCrypt hash算法还能解密啊?

3 Likes

技术学习,支持

1 Like

这个是解密客户端保存的密码吧

这个好呀,很多保存在软件上的密码可以读出来了

26 Likes

上面说的BCrypt加密指的实际上是哈希散列,是不可逆的(从信息论角度),终端密码存储基本采用加盐哈希散列。

Navicat不是数据库,也不是服务终点,它需要将密文解析成明文再连接数据库

而MySQL是服务的终点,它不需要明文存储密码,只需要将现有的散列和传入的密码散列进行对比,从信息论角度上是无法还原的

你给的源码我看了,AES解密,只针对Navicat,和MySQL和散列解密一点关系都没有

4 Likes

类似那些md5解密网站,弄一大堆数据。能碰撞上就算解开

其实大多数人建库,建用户之后,首先就是用 Navicat 之类的客户端连接试一试,然后放代码里调用,密码没了,首先就是找客户端软件和代码里的密码。如果存的密码代码里的密码都不对,只要 root 用户在直接改对应用户的密码就是了,非要费劲把数据库拖到本地改 hash 值也挺没必要的

666,学到了

。。。

3 Likes

From #dev to 开发调优

1 Like