Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2019-11043 — Python-эксплойт для CVE-2019-11043, нацеленный на недополнение буфера PHP-FPM, для достижения удаленного выполнения кода посредством перезаписи нулевого байта и манипуляции переменными FastCGI. | Kitploit
Инструменты/GitHubGitHub/lindemer/cve-2019-11043
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и ОбразованиеРазработка Полезной Нагрузки
GitHublindemer/cve-2019-11043

CVE-2019-11043

Python-эксплойт для CVE-2019-11043, нацеленный на недополнение буфера PHP-FPM, для достижения удаленного выполнения кода посредством перезаписи нулевого байта и манипуляции переменными FastCGI.

Репозиторий
4275 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2019-11043

Удаленное выполнение кода PHP-FPM

Screencast: https://youtu.be/d6benC5FVZM

Обзор

Этот эксплойт нулевого дня в распространенных конфигурациях PHP-FPM был обнаружен во время конкурса Realworld CTF в 2019 году. Регулярное выражение используется для разбора запрошенного URI, но символы новой строки %0a не сопоставляются. Это вызывает ошибку в FastCGI, которая неверно вычисляет длину строки запроса и записывает нулевой байт в позицию до начала предполагаемого буфера. Путем тщательного подбора длины строки запроса злоумышленник может использовать эту ошибку для перезаписи внутренних переменных PHP на сервере и выполнения произвольного шелл-кода.

Оригинальная реализация этого эксплойта на Go находится здесь. Я использовал её, статью и исходный отчет об ошибке в качестве учебных материалов для реализации эксплойта на Python.

Инструкции

Docker на Linux Запустите sudo docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043 для создания минимального сервера NGINX/PHP-FPM с пустым скриптом /script.php. Dockerfile для этого образа доступен здесь, хотя он не требуется для выполнения вышеуказанной команды.

Docker на Mac Запустите sudo docker-compose up -d из каталога /php/CVE-2019-11043 репозитория vulhub. (Compose входит в состав Docker для Mac.)

Запустите скрипт эксплойта командой python3 exploit.py http://localhost:8080/script.php (или /index.php, если использовался второй вариант). При успешном выполнении веб-шелл будет доступен путем добавления команд в URL после ?a= (например, http://localhost:8080/script.php?a=uname -a).

Примечание: Я пытался создать Ansible playbook для этого задания, но столкнулся с критической ошибкой, описанной здесь. Невозможно запустить systemd-сервисы на современных ядрах Linux (например, любой LTS-релиз Ubuntu) с помощью Ansible playbook.

Теория

Уязвимость

Конфигурационные файлы PHP-FPM содержат правило для сопоставления входящих URI-запросов с PHP-скриптами, которое часто выглядит так:

location ~ [^/]\.php(/|$) {
  ...
  fastcgi_split_path_info       ^(.+?\.php)(/.*)$;
  fastcgi_param PATH_INFO       $fastcgi_path_info;
  fastcgi_pass                  php:9000;
  ...
}

Это должно сопоставлять любой URI вида /script.php/pathinfo, но точка . на самом деле не сопоставляет символ новой строки %0a. Если URI содержит новую строку, это вызовет следующую ошибку в реализации PHP:

1141    int ptlen = strlen(pt);
1142    int slen = len - ptlen;
1143    int pilen = env_path_info ? strlen(env_path_info) : 0;
1144    int tflag = 0;
1145    char *path_info;
1146    if (apache_was_here) {
1147        /* recall that PATH_INFO won't exist */
1148        path_info = script_path_translated + ptlen;
1149        tflag = (slen != 0 && (!orig_path_info || strcmp(orig_path_info, path_info) != 0));
1150    } else {
1151        path_info = env_path_info ? env_path_info + pilen - slen : NULL;
1152        tflag = (orig_path_info != path_info);
1153    }

Проблема в том, что slen вычисляется правильно как длина URI минус длина пути к ресурсу, но pilen ошибочно устанавливается в 0. Это устанавливает path_info в отрицательное значение на строке 1151, что приводит к переполнению буфера вниз. Сразу после этого просчета в том же файле:

1159    FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
1160    old = path_info[0];
1161    path_info[0] = 0;
1162    if (!orig_script_name ||
1163        strcmp(orig_script_name, env_path_info) != 0) {
1164        if (orig_script_name) {
1165            FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
1166        }
1167        SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info);
1168    } else {
1169        SG(request_info).request_uri = orig_script_name;
1170    }
1171    path_info[0] = old;

На строке 1161 нулевой байт записывается в ошибочно вычисленную ячейку памяти с предыдущего шага. Это можно использовать для эксплуатации уязвимости на строке 1165, где FastCGI записывает переменную окружения. Записывая нулевой байт в указатель, управляющий операцией записи переменной окружения, мы можем вставлять произвольные переменные PHP в окружение с помощью наших HTTP-запросов.

Эксплойт

Внутренние структуры данных FastCGI

Переменные окружения в FastCGI хранятся в плотно упакованной последовательности пар строк «ключ-значение» в памяти. Начало и конец буфера, содержащего эти строки, называются _fcgi_data_seg. Член pos указывает на следующее доступное место для записи. Если буфер заполняется (pos > end), выделяется новый, а член next указывает на старый.

118    typedef struct _fcgi_data_seg {
119        char                  *pos;
120        char                  *end;
121    	   struct _fcgi_data_seg *next;
122    	   char                   data[1];
123    } fcgi_data_seg;

FastCGI обращается к отдельным переменным окружения с помощью хеш-таблицы под названием _fcgi_hash.

125    typedef struct _fcgi_hash {
126    	   fcgi_hash_bucket  *hash_table[FCGI_HASH_TABLE_SIZE];
127    	   fcgi_hash_bucket  *list;
128        fcgi_hash_buckets *buckets;
129        fcgi_data_seg     *data;
130    } fcgi_hash;

Идея состоит в том, чтобы перезаписать наименее значащий байт pos для обмана FastCGI, заставив его перезаписать существующую переменную. Код предполагается должен взять строку, добавленную к нашему URI-пути, и поместить её в расположение PATH_INFO. Однако мы хотим перезаписать PHP_VALUE, потому что это значение сразу извлекается и загружается в настройки PHP после уязвимого сегмента кода.

Выравнивание данных

Как видно в exploit.py, общая идея этого эксплойта — найти очень длинный URI-запрос, который выровняет внутренний буфер памяти FastCGI таким образом, чтобы мы могли им злоупотребить. Идея состоит в том, чтобы найти точное количество символов, необходимое для выделения FastCGI нового буфера _fcgi_data_seg. Когда это происходит, FastCGI предсказуемо записывает наш PATH_INFO в новый буфер, а сразу после этого — каждый из наших HTTP-заголовков как новые значения окружения. Итак, следующий шаг — найти, сколько символов нужно для дополнения произвольного HTTP-заголовка, чтобы выровнять память для наших целей. Поскольку мы ограничены записью одного нулевого байта в произвольное место, нам нужно, чтобы pos указывал на предсказуемое смещение относительно PHP_VALUE, чтобы изменение наименее значащего байта переместило его туда.

Скачать инструмент