# LFI2RCE через Вічне очікування {{#include ../../banners/hacktricks-training.md}} ## Основна інформація За замовчуванням, коли файл завантажується в PHP (навіть якщо він цього не очікує), він створить тимчасовий файл у `/tmp` з ім'ям, таким як **`php[a-zA-Z0-9]{6}`**, хоча я бачив деякі образи docker, де згенеровані файли не містять цифр. У випадку локального включення файлу, **якщо вам вдасться включити цей завантажений файл, ви отримаєте RCE**. Зверніть увагу, що за замовчуванням **PHP дозволяє завантажувати лише 20 файлів в одному запиті** (встановлено в `/etc/php//apache2/php.ini`): ``` ; Maximum number of files that can be uploaded via a single request max_file_uploads = 20 ``` Також, **кількість потенційних імен файлів становить 62\*62\*62\*62\*62\*62 = 56800235584** ### Інші техніки Інші техніки базуються на атаці протоколів PHP (ви не зможете цього зробити, якщо контролюєте лише останню частину шляху), розкритті шляху до файлу, зловживанні очікуваними файлами або **змушуючи PHP зазнати сегментаційної помилки, щоб завантажені тимчасові файли не були видалені**.\ Ця техніка **дуже схожа на останню, але не вимагає знаходження нульового дня**. ### Техніка вічного очікування У цій техніці **нам потрібно лише контролювати відносний шлях**. Якщо нам вдасться завантажити файли і зробити так, щоб **LFI ніколи не закінчувався**, у нас буде "досить часу", щоб **брутфорсити завантажені файли** і **знайти** будь-який з них. **Переваги цієї техніки**: - Вам потрібно лише контролювати відносний шлях всередині включення - Не вимагає nginx або несподіваного рівня доступу до лог-файлів - Не вимагає нульового дня для викликання сегментаційної помилки - Не вимагає розкриття шляху **Основні проблеми** цієї техніки: - Потрібні специфічні файли для присутності (може бути більше) - **Безумна** кількість потенційних імен файлів: **56800235584** - Якщо сервер **не використовує цифри**, загальна потенційна кількість становить: **19770609664** - За замовчуванням **можна завантажити лише 20 файлів** в **одному запиті**. - **Максимальна кількість паралельних робітників** використовуваного сервера. - Це обмеження разом з попередніми може зробити цю атаку занадто тривалою - **Тайм-аут для запиту PHP**. В ідеалі це має бути вічним або має вбивати процес PHP без видалення тимчасово завантажених файлів, якщо ні, це також буде проблемою Отже, як ви можете **зробити так, щоб включення PHP ніколи не закінчувалося**? Просто включивши файл **`/sys/kernel/security/apparmor/revision`** (**на жаль, не доступний у контейнерах Docker...**). Спробуйте це, просто викликавши: ```bash php -a # open php cli include("/sys/kernel/security/apparmor/revision"); ``` ## Apache2 За замовчуванням, Apache підтримує **150 одночасних з'єднань**, згідно з [https://ubiq.co/tech-blog/increase-max-connections-apache/](https://ubiq.co/tech-blog/increase-max-connections-apache/) це число можна збільшити до 8000. Слідкуйте за цим, щоб використовувати PHP з цим модулем: [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). За замовчуванням, (як я можу бачити в своїх тестах), **PHP процес може тривати вічно**. Давайте зробимо деякі розрахунки: - Ми можемо використовувати **149 з'єднань** для генерації **149 \* 20 = 2980 тимчасових файлів** з нашим веб-шеллом. - Потім, використати **остання з'єднання** для **брутфорсу** потенційних файлів. - При швидкості **10 запитів/с** часи такі: - 56800235584 / 2980 / 10 / 3600 \~= **530 годин** (50% шанс за 265 годин) - (без цифр) 19770609664 / 2980 / 10 / 3600 \~= 185 годин (50% шанс за 93 години) > [!WARNING] > Зверніть увагу, що в попередньому прикладі ми **повністю DoS-имо інших клієнтів**! Якщо сервер Apache буде покращено і ми зможемо зловживати **4000 з'єднаннями** (половина від максимальної кількості). Ми могли б створити `3999*20 = 79980` **файлів** і **число** зменшиться до приблизно **19.7 годин** або **6.9 годин** (10 годин, 3.5 години 50% шанс). ## PHP-FMP Якщо замість використання звичайного php моду для apache для виконання PHP скриптів **веб-сторінка використовує** **PHP-FMP** (це покращує ефективність веб-сторінки, тому його часто можна знайти), є ще щось, що можна зробити для покращення техніки. PHP-FMP дозволяє **налаштувати** **параметр** **`request_terminate_timeout`** в **`/etc/php//fpm/pool.d/www.conf`**.\ Цей параметр вказує максимальну кількість секунд **коли** **запит до PHP повинен завершитися** (безкінечно за замовчуванням, але **30 секунд, якщо параметр не закоментований**). Коли запит обробляється PHP, вказана кількість секунд, він **вбивається**. Це означає, що якщо запит завантажував тимчасові файли, тому що **обробка php була зупинена**, ці **файли не будуть видалені**. Отже, якщо ви можете зробити запит тривати цей час, ви можете **згенерувати тисячі тимчасових файлів**, які не будуть видалені, що **прискорить процес їх знаходження** і зменшує ймовірність DoS для платформи, споживаючи всі з'єднання. Отже, щоб **уникнути DoS**, припустимо, що **зловмисник буде використовувати лише 100 з'єднань** одночасно, а максимальний час обробки php за **php-fmp** (`request_terminate_timeout`**)** становить **30 секунд**. Отже, кількість **тимчасових файлів**, які можуть бути згенеровані **за секунду**, становить `100*20/30 = 66.67`. Тоді, щоб згенерувати **10000 файлів**, зловмиснику знадобиться: **`10000/66.67 = 150 секунд`** (щоб згенерувати **100000 файлів**, час становитиме **25 хвилин**). Тоді зловмисник міг би використовувати ці **100 з'єднань** для виконання **брутфорсу**. Припускаючи швидкість 300 запитів/с, час, необхідний для експлуатації цього, такий: - 56800235584 / 10000 / 300 / 3600 \~= **5.25 години** (50% шанс за 2.63 години) - (з 100000 файлами) 56800235584 / 100000 / 300 / 3600 \~= **0.525 години** (50% шанс за 0.263 години) Так, можливо згенерувати 100000 тимчасових файлів на середньому EC2 екземплярі:
> [!WARNING] > Зверніть увагу, що для активації тайм-ауту було б **досить включити вразливу LFI сторінку**, щоб вона потрапила в безкінечний цикл включення. ## Nginx Схоже, що за замовчуванням Nginx підтримує **512 паралельних з'єднань** одночасно (і це число можна покращити). {{#include ../../banners/hacktricks-training.md}}