說(shuō)明
今天手賤點(diǎn)了下 Profile 里的 change username,然后再次登錄就一直提示驗(yàn)證錯(cuò)誤了,于是有了本文
思路
帳號(hào)密碼肯定是存在 pg 里面的,那么進(jìn)入 pg 查看修改即可咯
登錄 pg 容器操作
# docker exec -it harbor-db /bin/bash
連接數(shù)據(jù)庫(kù):
postgres [ / ]$ psql -h 127.0.0.1 -p 5432 -d postgres -U postgres
查看有哪些數(shù)據(jù)庫(kù):
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
--------------+----------+----------+-------------+-------------+-----------------------
notaryserver | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres+
| | | | | server=CTc/postgres
notarysigner | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres+
| | | | | signer=CTc/postgres
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
registry | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
進(jìn)入數(shù)據(jù)庫(kù):
postgres=# \c registry;
查看數(shù)據(jù)庫(kù)里的表:
registry=# \dt
List of relations
Schema | Name | Type | Owner
--------+--------------------------+-------+----------
public | access | table | postgres
public | admin_job | table | postgres
public | alembic_version | table | postgres
public | artifact | table | postgres
public | artifact_blob | table | postgres
...
public | harbor_user | table | postgres
...
這里的 harbor_user 表比較可疑,進(jìn)去看看有哪些字段:
registry=# select * from harbor_user;
user_id | username | email | password | realname | comment | deleted | reset_uuid | salt | sysadmin_flag | creation_time | update_time | password_version
---------+-----------+-----------------------+----------------------------------+----------------+----------------+---------+------------+----------------------------------+---------------+----------------------------+----------------------------+------------------
2 | anonymous | anonymous@example.com | | anonymous user | anonymous user | t | | | f | 2020-12-08 09:33:42.526298 | 2020-12-08 10:27:16.581339 | sha1
1 | admin | admin@example.com | c24c0ec3e220ea5fda4a58ac6750649d | system admin | admin user | f | | qasbz0ctdynu8rnj8wi21cghv4iefimj | t | 2020-12-08 09:33:42.526298 | 2020-12-08 10:27:16.581339 | sha1
果然臊泌,帳號(hào)密碼是存儲(chǔ)在里面了,但是加密了揍拆,我該如何修改呢渠概?
google 了下,千篇一律的寫(xiě)著如下的語(yǔ)句嫂拴,然后原始密碼是 Harbor12345:
update harbor_user set password='a71a7d0df981a61cbb53a97ed8d78f3e', salt='ah3fdh5b7yxepalg9z45bu8zb36sszmr' where username='admin';
這樣更新一來(lái)有安全隱患播揪,二來(lái)沒(méi)辦法定義我想要的密碼(當(dāng)然也可以事后再去 web 里面去修改下),那么就稍微探查下如何定義這個(gè)更新語(yǔ)句吧筒狠。
密碼計(jì)算采用 pbkdf2 算法
參考源碼:https://github.com/goharbor/harbor/blob/master/src/common/dao/user.go
// ChangeUserPassword ...
func ChangeUserPassword(u models.User) error {
u.UpdateTime = time.Now()
u.Salt = utils.GenerateRandomString()
u.Password = utils.Encrypt(u.Password, u.Salt, utils.SHA256)
var err error
if u.PasswordVersion == utils.SHA1 {
u.PasswordVersion = utils.SHA256
_, err = GetOrmer().Update(&u, "Password", "PasswordVersion", "Salt", "UpdateTime")
} else {
_, err = GetOrmer().Update(&u, "Password", "Salt", "UpdateTime")
}
return err
}
寫(xiě)一個(gè) harbor 密碼修改程序
package main
import (
"crypto/sha1"
"crypto/sha256"
"fmt"
"golang.org/x/crypto/pbkdf2"
"hash"
"math/rand"
)
// harbor admin 密碼修改方法:
// update harbor_user set salt='', password='', password_version ='' where username='admin';
const (
// EncryptHeaderV1 ...
EncryptHeaderV1 = "<enc-v1>"
// SHA1 is the name of sha1 hash alg
SHA1 = "sha1"
// SHA256 is the name of sha256 hash alg
SHA256 = "sha256"
)
// HashAlg used to get correct alg for hash
var HashAlg = map[string]func() hash.Hash{
SHA1: sha1.New,
SHA256: sha256.New,
}
func GenerateRandomStringWithLen(length int) string {
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
l := len(chars)
result := make([]byte, length)
_, err := rand.Read(result)
if err != nil {
fmt.Printf("error reading random bytes: %v", err)
}
for i := 0; i < length; i++ {
result[i] = chars[int(result[i])%l]
}
return string(result)
}
func Encrypt(content string, salt string, encrptAlg string) string {
return fmt.Sprintf("%x", pbkdf2.Key([]byte(content), []byte(salt), 4096, 16, HashAlg[encrptAlg]))
}
func main() {
// 這要設(shè)置這里的明文密碼變量猪狈,就可以生成對(duì)應(yīng) salt、password 信息
password := "123456"
salt := GenerateRandomStringWithLen(32)
passwordEncry := Encrypt(password, salt, SHA256)
fmt.Printf("明文密碼: %s\nsalt: %s\npassword: %s\npassword_version: sha256\n", password, salt, passwordEncry)
}
只要修改這個(gè)腳本里的 password
變量辩恼,就可以生成 update 語(yǔ)句
# go run main.go
現(xiàn)在可以安心的數(shù)據(jù)庫(kù)修改密碼雇庙,將執(zhí)行產(chǎn)生的字符串帶入下面的單引號(hào)內(nèi)即可:
registry=# update harbor_user set salt='', password='', password_version ='' where username='admin';