# LFI2RCE via Eternal waiting {{#include ../../banners/hacktricks-training.md}} ## Podstawowe informacje Domyślnie, gdy plik jest przesyłany do PHP (nawet jeśli nie jest to oczekiwane), generowany jest plik tymczasowy w `/tmp` o nazwie takiej jak **`php[a-zA-Z0-9]{6}`**, chociaż widziałem niektóre obrazy dockera, 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 na przesyłanie tylko 20 plików w jednym żądaniu** (ustawione w `/etc/php//apache2/php.ini`): ``` ; Maximum number of files that can be uploaded via a single request max_file_uploads = 20 ``` Również, **liczba potencjalnych nazw plików wynosi 62\*62\*62\*62\*62\*62 = 56800235584** ### Inne techniki 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 **sprawieniu, by PHP doznało błędu segmentacji, aby przesyłane pliki tymczasowe nie zostały usunięte**.\ Ta technika jest **bardzo podobna do ostatniej, ale nie wymaga znalezienia zero day**. ### Technika wiecznego oczekiwania W tej technice **musimy tylko kontrolować względną ścieżkę**. Jeśli uda nam się przesłać pliki i sprawić, by **LFI nigdy się nie kończyło**, będziemy mieli "wystarczająco dużo czasu", aby **brute-forcować przesłane pliki** i **znaleźć** dowolny z przesłanych. **Zalety tej techniki**: - Musisz tylko kontrolować względną ścieżkę wewnątrz include - Nie wymaga nginx ani nieoczekiwanego poziomu dostępu do plików dziennika - Nie wymaga 0 day, aby spowodować błąd segmentacji - Nie wymaga ujawnienia ścieżki **Główne problemy** tej techniki to: - Potrzebne są konkretne pliki, aby były obecne (może być ich więcej) - **Szaleńcza** ilość potencjalnych nazw plików: **56800235584** - Jeśli serwer **nie używa cyfr**, całkowita potencjalna ilość wynosi: **19770609664** - Domyślnie **tylko 20 plików** może być przesłanych w **jednym żądaniu**. - **Maksymalna liczba równoległych pracowników** używanego serwera. - Ten limit w połączeniu z poprzednimi może sprawić, że atak będzie trwał zbyt długo - **Limit czasu dla żądania 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ż problem Jak więc możesz **sprawić, by include PHP nigdy się nie kończyło**? Po prostu przez dołączenie pliku **`/sys/kernel/security/apparmor/revision`** (**niestety niedostępny w kontenerach Docker...**). Spróbuj to zrobić, po prostu wywołując: ```bash 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/](https://ubiq.co/tech-blog/increase-max-connections-apache/) można zwiększyć tę liczbę do 8000. Postępuj zgodnie z tym, 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](https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04). Domyślnie, (jak mogę zobaczyć 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** z naszym webshell. - Następnie, użyj **ostatniego połączenia** do **brute-force** potencjalnych plików. - Przy prędkości **10 żądań/s** czasy są: - 56800235584 / 2980 / 10 / 3600 \~= **530 godzin** (50% szans w 265h) - (bez cyfr) 19770609664 / 2980 / 10 / 3600 \~= 185h (50% szans w 93h) > [!WARNING] > Zauważ, że w poprzednim przykładzie **całkowicie DoSujemy innych klientów**! Jeśli serwer Apache zostanie ulepszony i moglibyśmy nadużywać **4000 połączeń** (w połowie drogi do maksymalnej liczby). Moglibyśmy stworzyć `3999*20 = 79980` **plików** a **liczba** zostałaby **zmniejszona** do około **19.7h** lub **6.9h** (10h, 3.5h 50% szans). ## PHP-FMP Jeśli zamiast używać regularnego modułu php dla apache do uruchamiania skryptów PHP, **strona internetowa używa** **PHP-FMP** (to poprawia wydajność strony internetowej, więc często można to znaleźć), można zrobić coś innego, aby poprawić tę technikę. PHP-FMP pozwala na **konfigurację** **parametru** **`request_terminate_timeout`** w **`/etc/php//fpm/pool.d/www.conf`**.\ Ten parametr wskazuje maksymalną liczbę sekund **kiedy** **żądanie do PHP musi zakończyć się** (domyślnie nieskończoność, ale **30s, jeśli parametr jest odkomentowany**). Gdy żądanie jest przetwarzane przez PHP przez wskazaną 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 ten czas, możesz **wygenerować tysiące plików tymczasowych**, które nie zostaną usunięte, co **przyspieszy proces ich znajdowania** i zmniejsza prawdopodobieństwo DoS dla platformy poprzez wykorzystanie wszystkich połączeń. Aby **unikać DoS**, załóżmy, że **atakujący będzie używał tylko 100 połączeń** w tym samym czasie, a maksymalny czas przetwarzania PHP przez **php-fmp** (`request_terminate_timeout`**)** wynosi **30s**. Dlatego liczba **plików tymczasowych**, które mogą być generowane **na sekundę** wynosi `100*20/30 = 66.67`. Następnie, aby wygenerować **10000 plików**, atakujący potrzebowałby: **`10000/66.67 = 150s`** (aby wygenerować **100000 plików** czas wyniósłby **25min**). Następnie atakujący mógłby użyć tych **100 połączeń** do przeprowadzenia **brute-force**. Zakładając prędkość 300 req/s, czas potrzebny do wykorzystania tego jest następujący: - 56800235584 / 10000 / 300 / 3600 \~= **5.25 godzin** (50% szans w 2.63h) - (z 100000 plikami) 56800235584 / 100000 / 300 / 3600 \~= **0.525 godzin** (50% szans w 0.263h) Tak, możliwe jest wygenerowanie 100000 plików tymczasowych na instancji średniej wielkości EC2:
> [!WARNING] > Zauważ, że aby wywołać limit czasu, **wystarczy uwzględnić podatną stronę LFI**, aby weszła w wieczną pętlę dołączania. ## Nginx Wygląda na to, że domyślnie Nginx obsługuje **512 równoległych połączeń** w tym samym czasie (i ta liczba może być poprawiona). {{#include ../../banners/hacktricks-training.md}}