Категория > Новости > Команда упасть. Эксплуатируем критическую уязвимость в почтовике Exim 4 - «Новости»

Команда упасть. Эксплуатируем критическую уязвимость в почтовике Exim 4 - «Новости»


8-05-2018, 21:00. Автор: Calhoun

Содержание статьи

  • Работа с кучей
  • Эксплуатация
  • Выводы
Когда софтина попадает под пристальный взгляд экспертов по безопасности, велика вероятность, что за одним багом найдутся и другие. Так и случилось с агентом пересылки сообщений Exim: вслед за прошлогодней уязвимостью в нем найдена новая опасная дыра, действующая во всех версиях вплоть до последней (4.90.1). Поскольку Exim — штука популярная, список потенциально уязвимых целей просто огромен. Давай посмотрим, как эксплуатировать эту новую находку.

Обнаруженная проблема — это своеобразное продолжение предыдущего бага, который нашел тот же исследователь под ником Meh. На этот раз он раскопал возможность переполнения буфера в функции для работы с кодировкой Base64.


Уязвимость уже обзавелась своим идентификатором CVE-2018-6789 и получила статус критической, потому что приводит к удаленному выполнению любых команд на целевой системе с правами пользователя, от имени которого работает Exim. Причем не нужна ни авторизация, ни какой-либо другой уровень доступа. Нужен только коннект к порту SMTP.


Готовим инструменты


Под эту уязвимость существует добротно настроенный докер-контейнер, так что говорим спасибо товарищу под ником Skysider и запускаем:


$ docker run -it --rm --name exim -p 25:25 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined skysider/vulndocker:cve-2018-6789
[/code]

Пробрасываем из Docker стандартный порт, на котором висит SMTP.



Готовый стенд для эксплуатации Exim

Если нужна поддержка дебаггера, то не забудь его установить и перекомпилировать Exim с отладочными символами.


$ apt-get update && apt-get install -y gdb
$ cd exim-4.89
$ printf "CFLAGS += -gn" Local/Makefile
$ make
[/code]

Также нам понадобится Python с установленным pwntools для написания и тестирования эксплоита. Я просто разверну еще один докер-контейнер на основе Debian.


$ docker run -it --rm --link=exim debian /bin/bash
$ apt-get update && apt-get install -y python python-pip
$ pip install pwntools
[/code]

Все готово, вперед к победам!


Работа с кучей


Для начала взглянем на саму провинившуюся функцию.


/src/base64.c

153: b64decode(const uschar *code, uschar **ptr)
154: {
155: int x, y;
156: uschar *result = store_get(3*(Ustrlen(code)/4) + 1);
157:
158: *ptr = result;

За выделение требуемого количества памяти отвечает store_get — кастомная функция из набора для менеджмента памяти, который используется в составе Exim.


/src/store.h

30: #define store_extend(addr,old,new) 
31:
store_extend_3(addr, old, new, __FILE__, __LINE__)
32:
33: #define store_free(addr)
store_free_3(addr, __FILE__, __LINE__)
34: #define store_get(size)
store_get_3(size, __FILE__, __LINE__)
35: #define store_get_perm(size) store_get_perm_3(size, __FILE__, __LINE__)
36: #define store_malloc(size)
store_malloc_3(size, __FILE__, __LINE__)
37: #define store_release(addr)  store_release_3(addr, __FILE__, __LINE__)
38: #define store_reset(addr)
store_reset_3(addr, __FILE__, __LINE__)
...
43: extern BOOL
store_extend_3(void *, int, int, const char *, int);
44: extern void
store_free_3(void *, const char *, int);
45: extern void
*store_get_3(int, const char *, int);
46: extern void
*store_get_perm_3(int, const char *, int);
47: extern void
*store_malloc_3(int, const char *, int);
48: extern void
store_release_3(void *, const char *, int);
49: extern void
store_reset_3(void *, const char *, int);

Во время работы функции выделяется буфер размером 3*(len/4)+1 байт для хранения декодированных данных, где len — длина передаваемых данных.

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



Размеры выделяемой памяти для валидной и невалидной строки Base64

В общем случае, когда передаем строку размером 4n – 1, Exim зарезервирует 3n + 1 байт, но после декодирования получится строка, итоговый размер которой будет равен 3n + 2 байта, и это вызовет переполнение при попытке записи в выделенный буфер.


Где используется кодировка Base64? Да практически везде. Начиная от разных типов авторизаций и заканчивая файлами, которые прикрепляются к письмам. Все эти вещи потенциально уязвимы. Авторизация нам подходит, так как для отправки сообщений чаще всего потребуется валидный логин и пароль. На тестовом стенде уже включен механизм аутентификации CRAM-MD5, но подойдет и любой другой, который работает с Base64.


Теперь немножко поговорим о работе с памятью. Как я уже писал, в Exim существует самописный набор функций для этих целей. Функция store_malloc — вызов malloc прямиком из библиотеки glibc. Она занимается выделением блока памяти нужного размера.


Источник новостиgoogle.com
Перейти обратно к новости