7.6 KiB
Sonsuz Bekleme Yoluyla LFI2RCE
Sıfırdan kahraman olmaya kadar AWS hackleme öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!
HackTricks'i desteklemenin diğer yolları:
- Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız [ABONELİK PLANLARI]'na (https://github.com/sponsors/carlospolop) göz atın!
- Resmi PEASS & HackTricks ürünlerini edinin
- PEASS Ailesi'ni keşfedin, özel NFT'lerimiz koleksiyonumuz
- 💬 Discord grubuna veya telegram grubuna katılın veya bizi Twitter 🐦 @carlospolopm takip edin.**
- Hacking püf noktalarınızı göndererek HackTricks ve HackTricks Cloud github depolarına PR göndererek paylaşın.
Temel Bilgiler
Bir dosya PHP'ye yüklendiğinde (beklemese bile), php[a-zA-Z0-9]{6}
gibi bir isme sahip geçici bir dosya oluşturur /tmp
içinde, ancak bazı docker görüntülerinde oluşturulan dosyaların rakamlar içermediğini gördüm.
Yerel dosya dahilinde, yüklü dosyayı dahil etmeyi başarırsanız RCE alırsınız.
Varsayılan olarak PHP yalnızca tek bir istekte 20 dosya yüklemeye izin verir (ayarlanır /etc/php/<sürüm>/apache2/php.ini
):
; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20
Diğer teknikler
Diğer teknikler, PHP protokollerine saldırarak (yolun sadece son kısmını kontrol ediyorsanız başarılı olamazsınız), dosyanın yolunu ifşa ederek, beklenen dosyaları kötüye kullanarak veya PHP'yi bir segmentasyon hatası yaşatıp yüklenen geçici dosyaların silinmemesini sağlayarak çalışır. Bu teknik, bir sıfır gün bulmaya gerek olmadan son teknikle çok benzerdir.
Sonsuz bekleme tekniği
Bu teknikte yalnızca göreceli bir yol kontrol etmemiz gerekir. Eğer dosyaları yüklemeyi başarabilir ve LFI'nin hiç bitmemesini sağlarsak, "yeterince zamanımız" olacak ve yüklenen dosyalardan herhangi birini kaba kuvvet uygulayarak bulabileceğiz.
Bu tekniğin avantajları:
- Bir include içinde bir göreceli yol kontrol etmeniz yeterlidir
- Nginx veya log dosyalarına beklenmedik düzeyde erişim gerektirmez
- Bir segmentasyon hatası oluşturmak için bir sıfır gün gerektirmez
- Bir yol ifşası gerektirmez
Bu tekniğin ana sorunları şunlardır:
- Belirli bir dosyanın mevcut olması gerekmektedir (daha fazla olabilir)
- Potansiyel dosya adları için inanılmaz bir miktar: 56800235584
- Sunucu rakamlar kullanmıyorsa toplam potansiyel miktar: 19770609664
- Varsayılan olarak yalnızca bir istekte 20 dosya yüklenebilir.
- Kullanılan sunucunun maksimum eşzamanlı işçi sayısı.
- Bu sınırlama ile birlikte bu saldırının çok uzun sürmesine neden olabilir
- Bir PHP isteği için zaman aşımı. İdeal olarak bu sonsuz olmalı veya PHP işlemini silmeden geçici yüklenen dosyaları silmelidir, aksi takdirde bu da bir sorun olacaktır
Peki, bir PHP include'ı asla bitmeyecek şekilde nasıl yapabilirsiniz? Sadece /sys/kernel/security/apparmor/revision
dosyasını dahil ederek. (Ne yazık ki Docker konteynerlerinde mevcut değil...).
Denemek için sadece şunu çağırın:
php -a # open php cli
include("/sys/kernel/security/apparmor/revision");
Apache2
Apache, varsayılan olarak 150 eşzamanlı bağlantıyı destekler, https://ubiq.co/tech-blog/increase-max-connections-apache/ adresinde belirtildiği gibi bu sayıyı 8000'e kadar yükseltmek mümkündür. Bu modülle PHP kullanmak için şu adımları izleyin: https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04.
Varsayılan olarak (testlerimde gördüğüm kadarıyla), bir PHP işlemi sonsuza kadar sürebilir.
Şimdi biraz matematik yapalım:
- 149 bağlantı kullanarak 149 * 20 = 2980 geçici dosya oluşturabiliriz.
- Ardından, son bağlantıyı potansiyel dosyaları brute-force etmek için kullanın.
- 10 istek/s hızında zamanlar şunlardır:
- 56800235584 / 2980 / 10 / 3600 ~= 530 saat (265 saatte %50 olasılık)
- (ondalıksız) 19770609664 / 2980 / 10 / 3600 ~= 185 saat (93 saatte %50 olasılık)
{% hint style="warning" %} Önceki örnekte başka istemcileri tamamen DoS ediyoruz! {% endhint %}
Eğer Apache sunucusu geliştirilirse ve 4000 bağlantıyı (maksimum sayının yarısı) kullanabilirsek, 3999*20 = 79980
dosya oluşturabilir ve sayı yaklaşık olarak 19.7 saat veya 6.9 saat (10 saat, 3.5 saat %50 olasılık) olur.
PHP-FMP
Eğer web sayfası PHP betiklerini çalıştırmak için varsayılan php modunu değil de PHP-FMP'yi kullanıyorsa (bu web sayfasının verimliliğini artırır, bu yüzden sıkça karşılaşılır), tekniği geliştirmek için başka bir şey yapılabilir.
PHP-FMP, /etc/php/<php-sürümü>/fpm/pool.d/www.conf
içinde request_terminate_timeout
parametresini ayarlamaya izin verir.
Bu parametre, PHP'ye yapılan isteğin ne zaman sonlanması gerektiğini belirtir (varsayılan olarak sonsuzdur, ancak parametre yorumlanırsa 30 saniyedir). Bir istek PHP tarafından işlenirken belirtilen saniye sayısına ulaştığında, sonlandırılır. Bu, isteğin geçici dosyalar yüklediği durumda, çünkü php işlemi durdurulduğunda, bu dosyaların silinmeyeceği anlamına gelir. Dolayısıyla, bir isteği o süre boyunca sürdürebilirseniz, silinmeyecek binlerce geçici dosya oluşturabilirsiniz, bu da onları bulma sürecini hızlandırır ve tüm bağlantıları tüketerek platforma DoS olasılığını azaltır.
Bu nedenle, DoS'yi önlemek için bir saldırganın aynı anda yalnızca 100 bağlantıyı kullanacağını ve php-fmp tarafından belirlenen maksimum işlem süresinin (request_terminate_timeout
) 30 saniye olduğunu varsayalım. Dolayısıyla, saniyede oluşturulabilecek geçici dosya sayısı 100*20/30 = 66.67
olacaktır.
Sonra, 10000 dosya oluşturmak için bir saldırganın ihtiyacı olan süre: 10000/66.67 = 150 saniye
(100000 dosya oluşturmak için gereken süre ise 25 dakika olacaktır).
Ardından, saldırgan bu 100 bağlantıyı kullanarak bir arama brute-force gerçekleştirebilir. 300 istek/s hızında çalıştığını varsayarsak, bu saldırıyı gerçekleştirmek için gereken süre şöyledir:
- 56800235584 / 10000 / 300 / 3600 ~= 5.25 saat (2.63 saatte %50 olasılık)
- (100000 dosya ile) 56800235584 / 100000 / 300 / 3600 ~= 0.525 saat (0.263 saatte %50 olasılık)
Evet, bir EC2 orta boyutlu örneğinde 100000 geçici dosya oluşturmak mümkündür:
{% hint style="warning" %} Zaman aşımını tetiklemek için savunmasız LFI sayfasını içermek yeterlidir, böylece sonsuz bir dahil döngüye girer. {% endhint %}
Nginx
Varsayılan olarak Nginx'in aynı anda 512 paralel bağlantıyı desteklediği görünüyor (bu sayı artırılabilir).