Bu hafta sonu Windows 10 Bahar Güncellemesini yükledim ve yeni yerleşik OpenSSH araçlarıyla oynamaya başlayacağım için oldukça heyecanlıydım.
Windows yöneticilerinin artık Putty ve PPK formatlı anahtarları kullanması gerekmediği için OpenSSH’yi Windows’ta yerel olarak kullanmak harika. Etrafta dolaşıp hangi özelliklerin desteklendiğine dair daha fazla bilgi okumaya başladım ve şunu görünce hoş bir sürpriz yaşadım: ssh-agent.exe
dahildir.
Bu MSDN makalesinde yeni Windows ssh-agent’ın kullanımına ilişkin bazı referanslar buldum ve bu bölüm hemen dikkatimi çekti:
Geçmişte SSH aracılarının ele geçirilmesiyle çok eğlenmiştim, bu yüzden Windows’un bu yeni hizmetle özel anahtarlarınızı nasıl “güvenli bir şekilde” sakladığını görmeye karar verdim.
Bu yazıda metodolojimi ve bunu çözmeye yönelik adımları özetleyeceğim. Bu eğlenceli bir araştırma yolculuğuydu ve PowerShell ile çalışma konusunda daha iyi hale geldim.
tl;doktor
Özel anahtarlar DPAPI ile korunur ve HKCU kayıt defteri kovanında saklanır. RSA özel anahtarını kayıt defterinden çıkarmak ve yeniden oluşturmak için burada bazı PoC kodları yayınladım
Test ettiğim ilk şey, birkaç anahtar çifti oluşturmak için normal olarak OpenSSH yardımcı programlarını kullanmak ve bunları ssh aracısına eklemekti.
İlk olarak, kullanarak bazı şifre korumalı test anahtar çiftleri oluşturdum. ssh-keygen.exe
:
Sonra yeni olduğundan emin oldum. ssh-agent
hizmet çalışıyordu ve özel anahtar çiftlerini kullanarak çalışan aracıya ekledi ssh-add
:
Koşma ssh-add.exe -L
o anda SSH aracısı tarafından yönetilen anahtarları gösterir.
Son olarak, genel anahtarları bir Ubuntu kutusuna ekledikten sonra, özel anahtarlarımın şifresini çözmeye gerek kalmadan Windows 10’dan SSH girişi yapabileceğimi doğruladım (çünkü ssh-agent
bununla benim için ilgileniyor):
SSH Aracısının özel anahtarlarımı nasıl sakladığını ve okuduğunu anlamak için biraz araştırdım ve statik olarak inceleyerek başladım. ssh-agent.exe
. Ancak statik analiz becerilerimin çok zayıf olduğu ortaya çıktı, bu yüzden pes ettim ve süreci dinamik olarak izlemeye ve ne yaptığını görmeye karar verdim.
kullandım procmon.exe
Sysinternals’dan “ssh” içeren herhangi bir işlem adı için bir filtre eklendi.
İle procmon
Olayları yakaladıktan sonra tekrar SSH’yi Ubuntu makineme bağladım. Bütün olaylara baktığımda şunu gördüm: ssh.exe
Ubuntu’ya bir TCP bağlantısı açın ve sonunda gördüm ssh-agent.exe
harekete geçin ve Kayıt Defterinden bazı değerleri okuyun:
Aklıma iki şey geldi:
- süreç
ssh-agent.exe
HKCU\Software\OpenSSH\Agent\Keys’den değerleri okur - Bu değerleri okuduktan sonra hemen açılıyor
dpapi.dll
Bundan dolayı artık bir tür korumalı verinin Kayıt Defterinde saklandığını ve Kayıt Defterinden okunduğunu biliyordum ve ssh-agent
Microsoft’un Veri Koruma API’sini kullanıyordu
Tabii ki, Kayıt Defterine baktığımda, kullanarak eklediğim anahtarlar için iki giriş görebiliyordum. ssh-add
. Anahtar adları genel anahtarın parmak izleriydi ve birkaç ikili blob mevcuttu:
Kendime PowerShell’in çirkin sözdizimini (gelenek olduğu gibi) hatırlatmak için StackOverflow’u bir saat okuduktan sonra, kayıt defteri değerlerini alıp bunları değiştirebildim. “Yorum” alanı yalnızca ASCII kodlu metindi ve eklediğim anahtarın adıydı:
(default)
değer yalnızca anlamlı bir şeyin kodunu çözemeyen bir bayt dizisiydi. Eğer onu çekip şifresini nasıl çözeceğimi bulabilirsem, bunun “şifreli” özel anahtar olduğuna dair bir önsezim vardı. Baytları bir Powershell değişkenine çektim:
Her ne kadar birçok post-sömürme aracının sırları ve kimlik bilgilerini ortaya çıkarmak için onu kötüye kullandığını bilsem de DPAPI’ye pek aşina değildim, dolayısıyla diğer insanların muhtemelen bir sarmalayıcı uyguladığını biliyordum. Biraz Googling bana, hayal ettiğimden çok daha basit, tifaziz’in basit bir oneliner’ını buldu (tamam, sanırım insanların neden Powershell’i sevdiğini anlıyorum…. ;))
Bunun işe yarayıp yaramayacağını hâlâ bilmiyordum ama DPAPI kullanarak bayt dizisinin korumasını kaldırmaya çalıştım. Belki mükemmel biçimde oluşturulmuş bir OpenSSH özel anahtarının geri geleceğini umuyordum, bu yüzden sonucu base64 ile kodladım:
|
|
Geri dönen Base64, özel bir anahtar gibi görünmüyordu, ama yine de sırf eğlence olsun diye şifresini çözdüm ve orada “ssh-rsa” dizesini gördüğümde çok hoş bir sürpriz yaşadım! Doğru yolda olmam gerekiyordu.
Bu kısım aslında en uzun zamanımı aldı. Bir anahtarın bir tür ikili temsiline sahip olduğumu biliyordum, ancak formatı veya nasıl kullanılacağını çözemedim.
Çeşitli RSA anahtarları oluşturmakla uğraştım openssl
, puttygen
Ve ssh-keygen
ancak sahip olduğum ikili dosyaya benzeyecek hiçbir şey bulamadım.
Sonunda, çok fazla Google’da arama yaptıktan sonra, NetSPI’den, OpenSSH özel anahtarlarının bellek dökümlerinden çıkarılmasıyla ilgili harika bir blog yazısı buldum. ssh-agent
Linux’ta: https://blog.netspi.com/stealing-unencrypted-ssh-agent-keys-from-memory/
İkili format aynı olabilir mi? Blogdan bağlantısı verilen Python betiğini indirdim ve Windows kayıt defterinden aldığım korumasız base64 blob’unu besledim:
İşe yaradı! Orijinal yazar soleblaze’in ikili verinin doğru formatını nasıl bulduğuna dair hiçbir fikrim yok, ancak yaptığı ve paylaştığı için çok müteşekkirim. Harika Python aracı ve blog yazısı için tüm övgüler kendisine aittir.
Kayıt defterinden özel bir anahtar çıkarmanın mümkün olduğunu kendime kanıtladıktan sonra hepsini iki komut dosyasında bir araya getirdim.
GitHub Deposu
Birincisi bir Powershell betiğidir (extract_ssh_keys.ps1
) içinde kayıtlı anahtarlar için Kayıt Defterini sorgulayan ssh-agent
. Daha sonra ikili dosyanın korumasını kaldırmak ve Base64’e kaydetmek için mevcut kullanıcı bağlamıyla DPAPI’yi kullanır. Powershell’de İkili verileri ayrıştırmaya nasıl başlayacağımı bile bilmediğim için, tüm anahtarları daha sonra Python’a aktarabileceğim bir JSON dosyasına kaydettim. Powershell betiği yalnızca birkaç satırdan oluşur:
|
|
Kodu büyük ölçüde ödünç aldım parse_mem_python.py
soleblaze tarafından oluşturuldu ve bir sonraki komut dosyası için Python3’ü kullanacak şekilde güncellendi: extractPrivateKeys.py
. Powershell betiğinden oluşturulan JSON’u beslemek, bulunan tüm RSA özel anahtarlarının çıktısını alacaktır:
Bu RSA özel anahtarları şifrelenmemiş. Onları oluşturduğumda bir şifre eklemiş olmama rağmen, şifrelenmemiş olarak saklanıyorlar. ssh-agent
bu yüzden artık şifreye ihtiyacım yok.
Doğrulamak için anahtarı bir Kali linux kutusuna kopyaladım, parmak izini doğruladım ve bunu SSH’de kullandım!
Sonraki Adımlar
Açıkçası PowerShell-fu’m zayıf ve yayınladığım kod daha çok PoC için. Özel anahtarları tamamen PowerShell’de yeniden oluşturmak muhtemelen mümkündür. Ayrıca Python kodu için de kredi almıyorum – bunların hepsi onun orijinal uygulaması için tek başına alevlenmeli.
Ayrıca bunun silah haline getirilip kullanım sonrası çerçevelere eklendiğini de görmeyi çok isterim çünkü Windows 10’da yöneticiler tarafından çok daha fazla OpenSSH kullanımı görmeye başlayacağımızı düşünüyorum ve bu anahtarların redteamcılar ve pentester’lar için çok değerli olabileceğinden eminim 🙂
Geri bildirim ve yorumlar hoş geldiniz!
-ropnop’un tadını çıkarın