hacktricks/src/pentesting-web/file-inclusion/lfi2rce-via-eternal-waiting.md

98 lines
6.7 KiB
Markdown

# 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/<version>/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/<php-version>/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:
<figure><img src="../../images/image (240).png" alt=""><figcaption></figcaption></figure>
> [!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}}