← Tüm Projeler

Basic Pentesting Kolay

Makinenin kendisi kolaydı; asıl değerli kısım, kırılan bir SSH private key'in doğru parolaya rağmen çalışmamasının ardındaki OpenSSL 3.x uyumluluk sorununu kök nedenine kadar araştırıp elle çözmek oldu.

TryHackMe Tamamlandı Root-Cause Debugging

Özet

Bu rapor, TryHackMe'nin Basic Pentesting odasında kay kullanıcısının SSH private key'ini kırma ve kullanma sürecinde karşılaştığım, saatler süren bir takılmanın kök nedenini ve çözümünü belgeliyor. Sorun CTF'in kendisiyle değil, güncel Kali Linux'ta gelen OpenSSL 3.0.13'ün eski tip şifreli PEM key'leri okuyamamasıyla ilgili, iyi bilinen bir uyumluluk sorunuydu.

Key'in Kırılması ve Sorunun Tespiti

Key'in passphrase'inin kırılması:

ssh2john kay_id_rsa > forjohn.txt
john forjohn.txt --wordlist=/usr/share/wordlists/rockyou.txt
john --show forjohn.txt

Sonuç: passphrase doğru şekilde bulundu ve topluluktaki diğer write-up'larla birebir örtüşüyordu.

Not: Bu aşamada bir kullanım hatası da yapmıştım — john yanlışlıkla forjohn.txt yerine ham kay_id_rsa dosyasına karşı çalıştırılmış, bu da alakasız bir hash formatının yanlışlıkla algılanmasına ve boşa zaman harcanmasına yol açmıştı. Doğru komut her zaman ssh2john'un ürettiği hash dosyası üzerinde çalıştırılmalı.

Asıl sorun: Doğru passphrase bulunmasına rağmen hem

ssh -i kay_id_rsa kay@<target>

hem de

openssl rsa -in kay_id_rsa -out kay_id_rsa_new
ssh-keygen -p -f kay_id_rsa_new -N "" -m PEM

komutları şu hatayı veriyordu:

error in libcrypto: unsupported
Could not find private key from kay_id_rsa
...DECODER routines:OSSL_DECODER_from_bio:unsupported...
Input structure: EncryptedPrivateKeyInfo

Kök Nedenin Teşhisi

Key'in Proc-Type: 4,ENCRYPTED / DEK-Info: AES-128-CBC başlıklı "traditional" (PKCS#1) şifreli PEM formatında olduğunu belirledim. Bu format:

-provider legacy -provider default eklemek de sorunu çözmedi, çünkü asıl problem eksik bir şifreleme algoritması değil, decoder'ın bu PEM yapısını hiç tanıyamamasıydı (No supported data to decode).

Manuel Çözüm

openssl'in yüksek seviyeli komutlarını (openssl rsa, openssl pkey, ssh-keygen) tamamen atlayıp, düşük seviyeli openssl enc ile ham AES-128-CBC şifre çözme işlemini elle yaptım:

  1. DEK-Info satırından IV'yi çıkardım.
  2. Salt = IV'nin ilk 8 baytı.
  3. Anahtarı klasik EVP_BytesToKey algoritmasıyla (MD5(passphrase + salt)) Python ile elle türettim.
  4. openssl enc -d -aes-128-cbc -K <key> -iv <iv> -nopad ile ham DER verisini elde ettim.
  5. PKCS#7 padding'i kaldırıp, veriyi base64'e çevirip düz (şifresiz) bir PEM dosyası olarak yeniden sardım.
  6. openssl rsa -in ... -check -nooutRSA key ok — doğrulandı.
  7. Bu şifresiz key ile ssh -i sorunsuz çalıştı.

Neden Bu Sorun Oluşuyor?

Klasik ("traditional") şifreli PEM formatı şuna benzer:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,<16-byte-IV-hex>
<base64 ciphertext>
-----END RSA PRIVATE KEY-----

Bu format PKCS#8 değildir; şifreleme PEM header seviyesinde tanımlanır ve anahtar türetimi için tek turlu MD5 kullanılır. OpenSSL 3.0 ile gelen yeni mimaride key okuma işlemleri artık eski PEM_read_bio_PrivateKey yerine OSSL_DECODER_from_bio / OSSL_STORE API'lerinden geçiyor ve MD5 tabanlı eski KDF algoritması bazı yapılandırmalarda legacy provider'a taşınmış durumda (FIPS uyumluluğu için — MD5 FIPS'te devre dışı). Bazı OpenSSL 3.0.x/3.1.x sürümlerinde decoder'a selection parametresi doğru geçirilmediğinde key ya hiç tanınmıyor ya da bozuk veri üretiliyor — bu, OpenSSL'in kendi geliştiricileri tarafından da resmi olarak kabul edilip yamanmış bir bug.

Doğrulama

Sorunun gerçekliğini kanıtlamak için aynı key üzerinde şu denemeleri sırayla yaptım ve hepsi başarısız oldu:

openssl rsa    -in key.pem -passin pass:beeswax -out out.pem
openssl pkey   -in key.pem -passin pass:beeswax -out out.pem
openssl rsa    -provider legacy -provider default -in key.pem -passin pass:beeswax -out out.pem
openssl rsa    -inform PEM -in key.pem -passin pass:beeswax -out out.pem -traditional

Buna karşılık, düşük seviye openssl enc ile manuel AES-CBC çözme + elle yeniden PEM sarma işlemi sorunsuz çalıştı ve openssl rsa -check -noout çıktısı RSA key ok oldu. Bu, sorunun key'in kendisinde değil, OpenSSL'in yüksek seviye decoder katmanında olduğunu doğruladı.

Sonuç ve Öneriler

CTF cevapları doğruydu ve değişmemişti; sorun makinede veya odada değil, saldırgan makinesindeki (Kali) güncel OpenSSL sürümündeydi. Bu, 2023-2024 sonrası güncellenen Kali/Debian sistemlerinde giderek daha sık karşılaşılan bir sorun çünkü eski CTF makineleri hâlâ 2016-2018 döneminin OpenSSH/OpenSSL varsayılanlarıyla key üretiyor.

Gelecekte hızlı çözüm için: openssl rsa/ssh-keygen "unsupported"/"Could not read private key" hatası verirse önce -provider legacy -provider default -passin pass:... dene; işe yaramazsa doğrudan manuel openssl enc + Python KDF yöntemine geç — bu yöntem OpenSSL sürümünden bağımsız her zaman çalışır çünkü yüksek seviye decoder katmanını tamamen by-pass eder.

Tam Script

# 1) IV'yi key dosyasından çek (DEK-Info satırındaki hex kısmı)
IV=$(grep DEK-Info kay_id_rsa | cut -d',' -f2)

# 2) Şifreli veriyi (base64 body) çıkar ve decode et
tail -n +4 kay_id_rsa | head -n -1 | base64 -d > payload.bin

# 3) AES key'i türet (passphrase, salt=IV'nin ilk 8 baytı)
KEY=$(python3 -c "
import hashlib, binascii
iv = binascii.unhexlify('$IV')
salt = iv[:8]
d = d_i = b''
while len(d) < 16:
    d_i = hashlib.md5(d_i + b'beeswax' + salt).digest()
    d += d_i
print(d[:16].hex())
")

# 4) Ham AES-CBC deşifreleme (bozuk yüksek-seviye decoder'ı atlıyoruz)
openssl enc -d -aes-128-cbc -in payload.bin -out decrypted.der -K $KEY -iv $IV -nopad

# 5) PKCS7 padding'i kaldır ve yeniden PEM'e sar
python3 -c "
import base64
data = open('decrypted.der','rb').read()
der = data[:-data[-1]]
pem = '-----BEGIN RSA PRIVATE KEY-----\n' + base64.encodebytes(der).decode() + '-----END RSA PRIVATE KEY-----\n'
open('kay_id_rsa_final','w').write(pem)
"

chmod 600 kay_id_rsa_final

# 6) Doğrula
openssl rsa -in kay_id_rsa_final -check -noout

Resmi / Topluluk Kaynakları