LFI2RCE via Eternal waiting
Last updated
Last updated
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
За замовчуванням, коли файл завантажується в PHP (навіть якщо він цього не очікує), він створює тимчасовий файл у /tmp
з ім'ям, таким як php[a-zA-Z0-9]{6}
, хоча я бачив деякі образи docker, де згенеровані файли не містять цифр.
У випадку локального включення файлу, якщо вам вдасться включити цей завантажений файл, ви отримаєте RCE.
Зверніть увагу, що за замовчуванням PHP дозволяє завантажувати лише 20 файлів в одному запиті (встановлено в /etc/php/<version>/apache2/php.ini
):
Також, кількість потенційних імен файлів становить 62*62*62*62*62*62 = 56800235584
Інші техніки базуються на атаці протоколів PHP (ви не зможете, якщо контролюєте лише останню частину шляху), розкритті шляху до файлу, зловживанні очікуваними файлами або змушуючи PHP зазнати сегментаційної помилки, щоб завантажені тимчасові файли не були видалені. Ця техніка дуже схожа на останню, але не вимагає знаходження нульового дня.
У цій техніці нам потрібно лише контролювати відносний шлях. Якщо нам вдасться завантажити файли і зробити так, щоб LFI ніколи не закінчувався, у нас буде "досить часу", щоб брутфорсити завантажені файли та знайти будь-який з них.
Переваги цієї техніки:
Вам потрібно лише контролювати відносний шлях всередині включення
Не вимагає nginx або несподіваного рівня доступу до лог-файлів
Не вимагає нульового дня для викликання сегментаційної помилки
Не вимагає розкриття шляху
Основні проблеми цієї техніки:
Потрібні конкретні файли для присутності (може бути більше)
божевільна кількість потенційних імен файлів: 56800235584
Якщо сервер не використовує цифри, загальна потенційна кількість становить: 19770609664
За замовчуванням лише 20 файлів можуть бути завантажені в одному запиті.
максимальна кількість паралельних робітників використовуваного сервера.
Це обмеження разом з попередніми може зробити цю атаку занадто тривалою
Тайм-аут для PHP запиту. В ідеалі це має бути вічним або має вбивати процес PHP без видалення тимчасово завантажених файлів, якщо ні, це також буде проблемою
Отже, як ви можете зробити так, щоб PHP включення ніколи не закінчувалося? Просто включивши файл /sys/kernel/security/apparmor/revision
(на жаль, не доступний у контейнерах Docker...).
Спробуйте це, просто викликавши:
За замовчуванням, Apache підтримує 150 одночасних з'єднань, згідно з 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.
За замовчуванням, (як я можу бачити в своїх тестах), PHP процес може тривати вічно.
Давайте зробимо деякі розрахунки:
Ми можемо використовувати 149 з'єднань для генерації 149 * 20 = 2980 тимчасових файлів з нашим веб-шеллом.
Потім, використати остання з'єднання для брутфорсу потенційних файлів.
При швидкості 10 запитів/с часи такі:
56800235584 / 2980 / 10 / 3600 ~= 530 годин (50% шанс в 265 годин)
(без цифр) 19770609664 / 2980 / 10 / 3600 ~= 185 годин (50% шанс в 93 години)
Зверніть увагу, що в попередньому прикладі ми повністю DoS-имо інших клієнтів!
Якщо сервер Apache покращений і ми могли б зловживати 4000 з'єднаннями (половина від максимальної кількості). Ми могли б створити 3999*20 = 79980
файлів і число зменшилося б до приблизно 19.7 годин або 6.9 годин (10 годин, 3.5 години 50% шанс).
Якщо замість використання звичайного php моду для apache для виконання PHP скриптів веб-сторінка використовує PHP-FMP (це покращує ефективність веб-сторінки, тому його часто можна знайти), є ще щось, що можна зробити для покращення техніки.
PHP-FMP дозволяє налаштувати параметр request_terminate_timeout
в /etc/php/<php-version>/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 екземплярі:
Зверніть увагу, що для активації тайм-ауту було б досить включити вразливу LFI сторінку, щоб вона потрапила в безкінечний цикл включення.
Здається, за замовчуванням Nginx підтримує 512 паралельних з'єднань одночасно (і це число можна покращити).
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)