- 29 Eki 2018
- 2,745
- 626
Bu bölümde, dizin geçişi zafiyetinin ne olduğunu açıklayacak, dizin geçişi saldırılarının nasıl gerçekleştirileceğini ve yaygın engellerin nasıl aşılacağını anlatacak ve dizin geçişi güvenlik açıklarının nasıl önleneceğini açıklayacağız.
Laboratuvarlar
Dizin geçişinin temel kavramlarına aşinaysanız ve bunları bazı gerçekçi, kasıtlı olarak savunmasız bırakılmış hedefler üzerinde denemek istiyorsanız, bu konudaki tüm laboratuvarlara yorumlardan ulaşabilirsiniz.
Dizin geçişi zafiyeti nedir?
Dizin geçişi (file path traversal olarakta bilinir), bir saldırganın bir uygulamayı çalıştıran sunucudaki rastgele dosyaları okumasına olanak sağlayan bir web güvenlik açığıdır. Bu dosyalar arasında uygulama kodu ve verileri, arka uç sistemler için kimlik bilgileri ve hassas işletim sistemi dosyaları yer alabilir. Bazı durumlarda, bir saldırgan sunucudaki rastgele dosyalara yazarak uygulama verilerini veya davranışını değiştirebilir ve sonuç olarak sunucunun tam kontrolünü ele geçirebilir.
Dizin geçişi zafiyetiyle rastgele dosyaları okuma
Satılık ürünlerin fotoğraflarını gösteren bir alışveriş uygulaması düşünün. Fotoğraflar aşağıdaki gibi bir HTML aracılığıyla yüklenecektir:
loadImage bağlantısı bir filename parametresi alır ve belirtilen dosyanın içeriğini döndürür. Fotoğraf dosyalarının kendileri diskte /var/www/images/ konumunda saklanır. Bir fotoğrafı döndürmek için, uygulama istenen filename'i bu temel dizine ekler ve dosyanın içeriğini okumak için bir dosya sistemi API'si kullanır. Yukarıdaki durumda, uygulama aşağıdaki dosya yolundan okuma yapar:
Uygulama, dizin geçişi saldırılarına karşı hiçbir savunma uygulamamaktadır, bu nedenle bir saldırgan, sunucunun dosya sisteminden rastgele bir dosya almak için aşağıdaki URL'yi girebilir:
Bu, uygulamanın aşağıdaki dosya yolundan okumasına neden olur:
../ dizisi bir dosya yolu içinde geçerlidir ve dizin yapısında bir seviye yukarı çıkmak anlamına gelir. Ardışık üç ../ dizisi /var/www/images/ dizininden dosya sistemi kök dizinine çıkar ve böylece gerçekte okunan dosya şöyle olur:
Unix tabanlı işletim sistemlerinde bu, sunucuda kayıtlı kullanıcıların ayrıntılarını içeren standart bir dosyadır.
Windows'ta, hem "../" hem de "..\" geçerli dizin geçişi ifadeleridir ve bir standart işletim sistemi dosyasını almak için eşdeğer bir saldırı şu şekilde gerçekleştirilebilir:
Burada 1. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Dizin geçişi zafiyetlerinin kullanılmasında yaygın engeller
Burada 2. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
İç içe geçmiş dizin geçişi dizileri kullanabilirsiniz, örneğin ....// veya ....\/, iç dizin dizisi kaldırıldığında basit bir dizin geçişi dizisine geri döner.
Burada 3. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Bazı bağlamlarda, örneğin URL yolu veya bir multipart/form-data isteğinin filename parametresinde, web sunucuları girişinizi uygulamaya iletmek öncesinde herhangi bir dizin geçişi dizisini kaldırabilir. Bunun türündeki temizleme işlemlerini bazen URL kodlaması veya hatta çift URL kodlamasıyla (%2e%2e%2f veya %252e%252e%252f olarak) ../ karakterlerini geçebilirsiniz. Ayrıca, ..%c0%af veya ..%ef%bc%8f gibi çeşitli standart olmayan kodlamalar da işe yarayabilir.
Burada 4. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Eğer bir uygulama, kullanıcı tarafından sağlanan dosya adının beklenen temel klasörle başlaması gerektiğini talep ediyorsa, örneğin /var/www/images, o zaman istenen temel klasörü takip eden uygun dizin geçişi dizilerini dahil etmek mümkün olabilir. Örnek olarak:
Burada 5. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Bir uygulama, kullanıcı tarafından sağlanan dosya adının .png gibi beklenen bir dosya uzantısı ile bitmesini gerektiriyorsa, dosya yolunu gerekli uzantıdan önce etkin bir şekilde sonlandırmak için null bayt kullanmak mümkün olabilir. Örneğin:
Burada 6. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Dizin geçişi zafiyetlerini önlemenin en etkili yolu, kullanıcı tarafından sağlanan girdiyi hiçbir şekilde dosya sistemine aktarmamaktır. Bunu yapmak için birçok uygulama işlevi, aynı davranışı daha güvenli bir şekilde sunacak şekilde yeniden yazılabilir.
Eğer kullanıcı tarafından sağlanan girdiyi dosya sistemine aktarmaktan kaçınılamazsa, saldırıları önlemek için iki katmanlı bir savunma birlikte kullanılmalıdır:
Aşağıda, kullanıcı girdisine dayalı olarak bir dosyanın kanonik yolunu doğrulamak için basit bir Java kodu örneği bulunmaktadır:
Laboratuvarlar
Dizin geçişinin temel kavramlarına aşinaysanız ve bunları bazı gerçekçi, kasıtlı olarak savunmasız bırakılmış hedefler üzerinde denemek istiyorsanız, bu konudaki tüm laboratuvarlara yorumlardan ulaşabilirsiniz.
Dizin geçişi zafiyeti nedir?
Dizin geçişi (file path traversal olarakta bilinir), bir saldırganın bir uygulamayı çalıştıran sunucudaki rastgele dosyaları okumasına olanak sağlayan bir web güvenlik açığıdır. Bu dosyalar arasında uygulama kodu ve verileri, arka uç sistemler için kimlik bilgileri ve hassas işletim sistemi dosyaları yer alabilir. Bazı durumlarda, bir saldırgan sunucudaki rastgele dosyalara yazarak uygulama verilerini veya davranışını değiştirebilir ve sonuç olarak sunucunun tam kontrolünü ele geçirebilir.
Dizin geçişi zafiyetiyle rastgele dosyaları okuma
Satılık ürünlerin fotoğraflarını gösteren bir alışveriş uygulaması düşünün. Fotoğraflar aşağıdaki gibi bir HTML aracılığıyla yüklenecektir:
HTML:
<img src="/loadImage?filename=218.png">
loadImage bağlantısı bir filename parametresi alır ve belirtilen dosyanın içeriğini döndürür. Fotoğraf dosyalarının kendileri diskte /var/www/images/ konumunda saklanır. Bir fotoğrafı döndürmek için, uygulama istenen filename'i bu temel dizine ekler ve dosyanın içeriğini okumak için bir dosya sistemi API'si kullanır. Yukarıdaki durumda, uygulama aşağıdaki dosya yolundan okuma yapar:
Kod:
/var/www/images/218.png
Uygulama, dizin geçişi saldırılarına karşı hiçbir savunma uygulamamaktadır, bu nedenle bir saldırgan, sunucunun dosya sisteminden rastgele bir dosya almak için aşağıdaki URL'yi girebilir:
HTTP:
https://insecure-website.com/loadImage?filename=../../../etc/passwd
Bu, uygulamanın aşağıdaki dosya yolundan okumasına neden olur:
Kod:
/var/www/images/../../../etc/passwd
../ dizisi bir dosya yolu içinde geçerlidir ve dizin yapısında bir seviye yukarı çıkmak anlamına gelir. Ardışık üç ../ dizisi /var/www/images/ dizininden dosya sistemi kök dizinine çıkar ve böylece gerçekte okunan dosya şöyle olur:
Kod:
/etc/passwd
Unix tabanlı işletim sistemlerinde bu, sunucuda kayıtlı kullanıcıların ayrıntılarını içeren standart bir dosyadır.
Windows'ta, hem "../" hem de "..\" geçerli dizin geçişi ifadeleridir ve bir standart işletim sistemi dosyasını almak için eşdeğer bir saldırı şu şekilde gerçekleştirilebilir:
HTTP:
https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini
Burada 1. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Dizin geçişi zafiyetlerinin kullanılmasında yaygın engeller
- Kullanıcı girdisini dosya yollarına yerleştiren birçok uygulama, genellikle dizin geçişi saldırılarına karşı bir tür savunma mekanizması kullanır; ancak bu savunmalar genellikle atlatılabilir.
- Eğer bir uygulama, kullanıcı tarafından sağlanan dosya adından dizin geçişi dizilerini kaldırıyorsa veya engelliyorsa, çeşitli teknikler kullanarak savunmayı atlamak mümkün olabilir.
- Herhangi bir çaprazlama dizisi kullanmadan bir dosyaya doğrudan başvurmak için filename=/etc/passwd gibi dosya sistemi kökünden mutlak bir yol kullanabilirsiniz.
Burada 2. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
İç içe geçmiş dizin geçişi dizileri kullanabilirsiniz, örneğin ....// veya ....\/, iç dizin dizisi kaldırıldığında basit bir dizin geçişi dizisine geri döner.
Burada 3. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Bazı bağlamlarda, örneğin URL yolu veya bir multipart/form-data isteğinin filename parametresinde, web sunucuları girişinizi uygulamaya iletmek öncesinde herhangi bir dizin geçişi dizisini kaldırabilir. Bunun türündeki temizleme işlemlerini bazen URL kodlaması veya hatta çift URL kodlamasıyla (%2e%2e%2f veya %252e%252e%252f olarak) ../ karakterlerini geçebilirsiniz. Ayrıca, ..%c0%af veya ..%ef%bc%8f gibi çeşitli standart olmayan kodlamalar da işe yarayabilir.
Burada 4. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Eğer bir uygulama, kullanıcı tarafından sağlanan dosya adının beklenen temel klasörle başlaması gerektiğini talep ediyorsa, örneğin /var/www/images, o zaman istenen temel klasörü takip eden uygun dizin geçişi dizilerini dahil etmek mümkün olabilir. Örnek olarak:
Kod:
filename=/var/www/images/../../../etc/passwd
Burada 5. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Bir uygulama, kullanıcı tarafından sağlanan dosya adının .png gibi beklenen bir dosya uzantısı ile bitmesini gerektiriyorsa, dosya yolunu gerekli uzantıdan önce etkin bir şekilde sonlandırmak için null bayt kullanmak mümkün olabilir. Örneğin:
Kod:
filename=../../../etc/passwd%00.png
Burada 6. laboratuvar yer almakta, yorumlardan ulaşabilirsiniz.
Dizin geçişi zafiyetlerini önlemenin en etkili yolu, kullanıcı tarafından sağlanan girdiyi hiçbir şekilde dosya sistemine aktarmamaktır. Bunu yapmak için birçok uygulama işlevi, aynı davranışı daha güvenli bir şekilde sunacak şekilde yeniden yazılabilir.
Eğer kullanıcı tarafından sağlanan girdiyi dosya sistemine aktarmaktan kaçınılamazsa, saldırıları önlemek için iki katmanlı bir savunma birlikte kullanılmalıdır:
- Uygulama, kullanıcı girdisini işlemeye başlamadan önce doğrulama yapmalıdır. İdeal olarak, doğrulama izin verilen değerlerin bir beyaz listesiyle karşılaştırma yapmalıdır. Gerekli işlevsellik için bunun mümkün olmadığı durumlarda, doğrulama girdinin sadece izin verilen içeriği içerdiğini, sadece alfasayısal karakterlerden oluştuğunu doğrulamalıdır.
- Sağlanan girdiyi doğruladıktan sonra, uygulama girdiyi temel dizine eklemeli ve bir platform dosya sistemi API'si kullanarak yolun kanonik hale getirilmesini sağlamalıdır. Kanonik hale getirilen yolun beklenen temel dizinle başladığını doğrulamalıdır.
Aşağıda, kullanıcı girdisine dayalı olarak bir dosyanın kanonik yolunu doğrulamak için basit bir Java kodu örneği bulunmaktadır:
Java:
File file = new File(BASE_DIRECTORY, userInput);
if (file.getCanonicalPath().startsWith(BASE_DIRECTORY)) {
// process file
}
Son düzenleme: