LFI2RCE via Eternal waiting
Основна інформація
За замовчуванням, коли файл завантажується в 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 ніколи не завершується, у нас буде "достатньо часу" для перебору завантажених файлів та знаходження будь-якого з завантажених.
Переваги цієї техніки:
Вам потрібно лише контролювати відносний шлях всередині include
Не потребує nginx або неочікуваного рівня доступу до файлів журналу
Не потребує 0-дня для виклику сегментаційної помилки
Не потребує розкриття шляху
Основні проблеми цієї техніки:
Потрібно, щоб були присутні конкретні файли (їх може бути більше)
Божевільна кількість потенційних імен файлів: 56800235584
Якщо сервер не використовує цифри, загальна потенційна кількість становить: 19770609664
За замовчуванням лише 20 файлів можуть бути завантажені за один запит.
Максимальна кількість паралельних робітників використовуваного сервера.
Це обмеження разом з попередніми може зробити цю атаку занадто тривалою
Тайм-аут для запиту PHP. Ідеально це повинно бути вічним або повинно завершувати процес PHP без видалення тимчасово завантажених файлів, якщо ні, це також буде проблемою
Отже, як ви можете зробити включення PHP ніколи не завершується? Просто включивши файл /sys/kernel/security/apparmor/revision
(на жаль, недоступний в контейнерах Docker).
Спробуйте це просто викликавши:
Apache2
За замовчуванням 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 години)
Зверніть увагу, що в попередньому прикладі ми повністю DoSing інших клієнтів!
Якщо сервер 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/<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
Здається, за замовчуванням Nginx підтримує 512 паралельних підключень одночасно (і це число можна покращити).
Last updated