LFI2RCE via Eternal waiting

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Domyślnie, gdy plik jest przesyłany do PHP (nawet jeśli nie jest tego oczekiwany), zostanie wygenerowany tymczasowy plik w /tmp o nazwie takiej jak php[a-zA-Z0-9]{6}, chociaż widziałem niektóre obrazy Docker, w których generowane pliki nie zawierają cyfr.

W przypadku lokalnego włączenia pliku, jeśli uda ci się dołączyć ten przesłany plik, uzyskasz RCE.

Zauważ, że domyślnie PHP pozwala tylko na przesłanie 20 plików w pojedynczym żądaniu (ustawione w /etc/php/<wersja>/apache2/php.ini):

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

Inna technika

Inne techniki polegają na atakowaniu protokołów PHP (nie będziesz w stanie, jeśli kontrolujesz tylko ostatnią część ścieżki), ujawnianiu ścieżki pliku, nadużywaniu oczekiwanych plików lub spowodowaniu awarii segmentacji PHP, aby tymczasowe pliki nie były usuwane. Ta technika jest bardzo podobna do poprzedniej, ale nie wymaga znajdowania dziury zero day.

Technika wiecznego oczekiwania

W tej technice musimy kontrolować tylko ścieżkę względną. Jeśli uda nam się przesłać pliki i spowodować, że LFI nigdy się nie zakończy, będziemy mieli "wystarczająco dużo czasu" na próbne przeszukanie przesłanych plików i znalezienie któregokolwiek z nich.

Zalety tej techniki:

  • Wystarczy kontrolować ścieżkę względną wewnątrz include

  • Nie wymaga nginx ani nieoczekiwanego poziomu dostępu do plików dziennika

  • Nie wymaga dziury zero day do spowodowania awarii segmentacji

  • Nie wymaga ujawnienia ścieżki

Główne problemy tej techniki to:

  • Konieczność obecności określonego pliku(lub plików) (może być ich więcej)

  • Szalona ilość potencjalnych nazw plików: 56800235584

  • Jeśli serwer nie używa cyfr, całkowita potencjalna liczba wynosi: 19770609664

  • Domyślnie w jednym żądaniu można przesłać tylko 20 plików.

  • Maksymalna liczba równoległych pracowników używanego serwera.

  • To ograniczenie w połączeniu z poprzednimi może sprawić, że ten atak potrwa zbyt długo

  • Limit czasu na żądanie PHP. Idealnie powinien być wieczny lub powinien zabić proces PHP bez usuwania tymczasowo przesłanych plików, w przeciwnym razie będzie to również problematyczne

Więc, jak można spowodować, że include PHP nigdy się nie zakończy? Po prostu poprzez dołączenie pliku /sys/kernel/security/apparmor/revision (niestety niedostępny w kontenerach Docker).

Spróbuj to wywołać tylko:

php -a # open php cli
include("/sys/kernel/security/apparmor/revision");

Apache2

Domyślnie Apache obsługuje 150 równoczesnych połączeń, zgodnie z https://ubiq.co/tech-blog/increase-max-connections-apache/ można zwiększyć tę liczbę do 8000. Postępuj zgodnie z tym poradnikiem, aby używać PHP z tym modułem: https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04.

Domyślnie (jak widzę w moich testach), proces PHP może trwać wiecznie.

Zróbmy trochę matematyki:

  • Możemy użyć 149 połączeń do wygenerowania 149 * 20 = 2980 plików tymczasowych za pomocą naszego webshell.

  • Następnie użyj ostatniego połączenia do brute-force'owania potencjalnych plików.

  • Przy prędkości 10 żądań/s czasy to:

  • 56800235584 / 2980 / 10 / 3600 ~= 530 godzin (50% szans w 265h)

  • (bez cyfr) 19770609664 / 2980 / 10 / 3600 ~= 185h (50% szans w 93h)

Zauważ, że w poprzednim przykładzie całkowicie DoSingujesz innych klientów!

Jeśli serwer Apache zostanie ulepszony i będziemy mogli nadużyć 4000 połączeń (połowa maksymalnej liczby), moglibyśmy utworzyć 3999*20 = 79980 plików i liczba zostałaby zmniejszona do około 19.7h lub 6.9h (10h, 3.5h 50% szans).

PHP-FMP

Jeśli zamiast używać zwykłego modułu php dla apache do uruchamiania skryptów PHP, strona internetowa używa PHP-FMP (co poprawia wydajność strony internetowej, więc jest to częste), istnieje coś innego, co można zrobić, aby poprawić technikę.

PHP-FMP pozwala na konfigurację parametru request_terminate_timeout w /etc/php/<wersja-php>/fpm/pool.d/www.conf. Ten parametr wskazuje maksymalną liczbę sekund, kiedy żądanie do PHP musi zostać zakończone (domyślnie nieskończone, ale 30s, jeśli parametr jest odkomentowany). Gdy żądanie jest przetwarzane przez PHP przez określoną liczbę sekund, jest zabijane. Oznacza to, że jeśli żądanie przesyłało pliki tymczasowe, ponieważ przetwarzanie php zostało zatrzymane, te pliki nie zostaną usunięte. Dlatego jeśli możesz sprawić, aby żądanie trwało tyle czasu, możesz wygenerować tysiące plików tymczasowych, które nie zostaną usunięte, co przyspieszy proces ich znalezienia i zmniejszy prawdopodobieństwo DoS na platformie poprzez zużycie wszystkich połączeń.

Aby uniknąć DoS, załóżmy, że atakujący będzie używał tylko 100 połączeń jednocześnie, a maksymalny czas przetwarzania PHP przez php-fmp (request_terminate_timeout) wynosi 30s. Dlatego liczba plików tymczasowych, które można wygenerować na sekundę, wynosi 100*20/30 = 66.67.

Następnie, aby wygenerować 10000 plików, atakującemu będzie potrzebne: 10000/66.67 = 150s (aby wygenerować 100000 plików czas wyniósłby 25 minut).

Następnie atakujący mógłby użyć tych 100 połączeń do przeprowadzenia brute-force'owania. **** Przy założeniu prędkości 300 żądań/s czas potrzebny do wykorzystania tego jest następujący:

  • 56800235584 / 10000 / 300 / 3600 ~= 5.25 godziny (50% szans w 2.63h)

  • (z 100000 plikami) 56800235584 / 100000 / 300 / 3600 ~= 0.525 godziny (50% szans w 0.263h)

Tak, jest możliwe wygenerowanie 100000 plików tymczasowych na średnim rozmiarze instancji EC2:

Zauważ, że aby spowodować przekroczenie czasu oczekiwania, wystarczy dołączyć podatną stronę LFI, aby wpadła w wieczną pętlę dołączania.

Nginx

Wygląda na to, że domyślnie Nginx obsługuje 512 równoczesnych połączeń (i ta liczba może być zwiększona).

Last updated