7.8 KiB
Sonsuz Bekleme ile LFI2RCE
htARTE (HackTricks AWS Red Team Expert) ile sıfırdan kahraman olmak için AWS hackleme öğrenin!
HackTricks'i desteklemenin diğer yolları:
- Şirketinizi HackTricks'te reklamını görmek veya HackTricks'i PDF olarak indirmek için ABONELİK PLANLARI'na göz atın!
- Resmi PEASS & HackTricks ürünlerini edinin
- The PEASS Ailesi'ni keşfedin, özel NFT'lerimiz koleksiyonumuz
- 💬 Discord grubuna veya telegram grubuna katılın veya Twitter 🐦 @carlospolopm'ı takip edin.
- Hacking hilelerinizi HackTricks ve HackTricks Cloud github depolarına PR göndererek paylaşın.
Temel Bilgiler
PHP'ye bir dosya yüklendiğinde (beklemese bile), varsayılan olarak /tmp
dizininde php[a-zA-Z0-9]{6}
gibi bir isimle geçici bir dosya oluşturulur. 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 elde edersiniz.
Unutmayın ki varsayılan olarak PHP, tek bir istekte 20 dosya yüklemeye izin verir (/etc/php/<sürüm>/apache2/php.ini
'de ayarlanır):
; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20
Ayrıca, potansiyel dosya adı sayısı 62*62*62*62*62*62 = 56800235584'dir.
Diğer teknikler
Diğer teknikler, PHP protokollerine saldırmayı (yolu sadece son bölümü kontrol ediyorsanız başaramazsınız), dosyanın yolunu ifşa etmeyi, beklenen dosyaları kötüye kullanmayı veya PHP'yi bir segmentasyon hatasıyla karşılaştırmayı sağlayarak yüklenen geçici dosyaların silinmemesini sağlamayı içerir.
Bu teknik, bir sıfır gün bulma gereksinimi olmadan son teknikle çok benzerdir.
Sonsuz bekleme tekniği
Bu teknikte, yalnızca bir göreceli yol kontrol etmemiz gerekmektedir. Dosyaları yüklemeyi başarır ve LFI hiç bitmezse, yüklenen dosyalardan herhangi birini brute-force yaparak bulmak için "yeterli zaman"ımız olacaktır.
Bu teknikle ilgili avantajlar:
- Bir include içinde yalnızca bir göreceli yolu kontrol etmeniz yeterlidir
- Nginx veya beklenmeyen düzeyde erişim log dosyalarına ihtiyaç duymaz
- Bir segmentasyon hatası oluşturmak için bir sıfır gün gerektirmez
- Bir yol ifşası gerektirmez
Bu tekniklerin ana sorunları şunlardır:
- Belirli bir dosyanın (daha fazla olabilir) mevcut olması gerekmektedir
- Çılgınca miktarda potansiyel dosya adı: 56800235584
- Sunucu rakamlar kullanmıyorsa toplam potansiyel miktar: 19770609664
- Varsayılan olarak yalnızca 20 dosya, tek bir istekte yüklenebilir.
- Kullanılan sunucunun eşzamanlı çalışanların maksimum sayısı.
- Bu sınırlama, diğerleriyle 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'ını 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...).
Bunu denemek için sadece aşağıdaki komutu çağırın:
php -a # open php cli
include("/sys/kernel/security/apparmor/revision");
Apache2
Varsayılan olarak, Apache 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. PHP'yi bu modülle 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.
Biraz matematik yapalım:
- 149 bağlantıyı web kabuğumuzla birlikte 149 * 20 = 2980 geçici dosya oluşturmak için kullanabiliriz.
- 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)
- (rakamlar olmadan) 19770609664 / 2980 / 10 / 3600 ~= 185 saat (93 saatte %50 olasılık)
{% hint style="warning" %} Önceki örnekte diğer istemcileri tamamen DoS ediyoruz! {% endhint %}
Eğer Apache sunucusu iyileştirilirse ve 4000 bağlantıyı (maksimum sayının yarısı) kullanabilirsek, 3999*20 = 79980
dosya oluşturabiliriz ve süre yaklaşık olarak 19.7 saat veya 6.9 saat (10 saat, 3.5 saatte %50 olasılık) azalır.
PHP-FPM
Eğer web sayfası PHP betiklerini çalıştırmak için düzenli php modu yerine PHP-FPM kullanıyorsa (bu web sayfasının verimliliğini artırır, bu yüzden sıkça karşılaşılır), teknikleri iyileştirmek için başka bir şey yapılabilir.
PHP-FPM, /etc/php/<php-sürümü>/fpm/pool.d/www.conf
yolunda request_terminate_timeout
parametresini yapılandırmaya izin verir.
Bu parametre, PHP'ye yapılan isteğin sonlandırılması gereken maksimum saniye sayısını belirtir (varsayılan olarak sonsuz, ancak parametre yorum satırı değilse 30 saniye). Bir istek PHP tarafından işlenirken belirtilen saniye sayısına ulaşırsa, sonlandırılır. Bu, istek geçici dosyalar yükleniyorsa, çünkü php işlemi durduğunda, bu dosyaların silinmeyeceği anlamına gelir. Bu nedenle, bir isteği bu 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 bir DoS olasılığını azaltır.
Bu nedenle, bir saldırganın aynı anda yalnızca 100 bağlantıyı kullanacağını ve php-fpm tarafından belirlenen php maksimum işlem süresinin (request_terminate_timeout
) 30 saniye olduğunu varsayalım. Bu durumda, saniye başına oluşturulan geçici dosya sayısı 100*20/30 = 66.67
olur.
Dolayısıyla, bir saldırganın 10000 dosya oluşturması için gereken süre: 10000/66.67 = 150 saniye
(100000 dosya oluşturmak için gereken süre ise 25 dakika olur).
Saldırgan, bu 100 bağlantıyı bir arama brute-force işlemi gerçekleştirmek için kullanabilir. 300 istek/s hızında çalıştığını varsayarsak, bu işlemi gerçekleştirmek için gereken süre aşağıdaki gibidir:
- 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 örnekte 100000 geçici dosya oluşturmak mümkündür:
{% hint style="warning" %} Zaman aşımını tetiklemek için yalnızca kaynak kodu açık olan LFI sayfasını dahil etmek yeterlidir, böylece sonsuz bir dahil döngüsüne girer. {% endhint %}
Nginx
Varsayılan olarak, Nginx'in aynı anda 512 paralel bağlantıyı desteklediği görünüyor (ve bu sayı iyileştirilebilir).