...

Приоткрывая завесу

Примеры важных уязвимостей форматирующей строки

Кроме упомянутой уязвимости форматирующей строки FTP-демона Вашингтонского университета при передаче параметра команде SITE EXEC, следует пару слов сказать о некоторых других уязвимостях. Часть из них была использована саморазмножающимися вирусами (червями) и утилитами, нашедшими широкое применение среди злоумышленников, в результате применения которых были скомпрометированы тысячи хостов.

IRIX telnetdclient. Включенные в форматирующую строку данные клиента, которая передавалась как параметр функции syslog(), позволяли удаленному злоумышленнику выполнить произвольный код безо всякой аутентификации. Эта уязвимость была обнаружена Last Stage of Delirium. Дополнительные сведения можно найти по адресу www.securityfocus.com/bid/1572.

Linux rpc.statd. Эта уязвимость форматирующей строки также обязана своим происхождением неправильному использованию функции syslog(). Она позволяет удаленному злоумышленнику получить права суперпользователя. Уязвимость была обнаружена Дэниелом Джакобоуитцом (Daniel Jacobowitz) и опубликована 16 июля 2000 года в извещении Bugtraq. Материалы по данному вопросу опубликованы по адресу www.securityfocus.com/bid/1480.

Cfingerd. Очередная уязвимость форматирующей строки функции syslog() была обнаружена Мигелем Ласзло (Megyer Laszlo). Если злоумышленник успешно воспользуется ей, то он получит возможность удаленно управлять основным хостом. Описание уязвимости может быть найдено по адресу www.securityfocus.com/bid/2576. Multiple Vendor LibC Locale Implementation. Юко Пуннонен (Jouko Pynn^en) и Core SDI независимо друг от друга обнаружили уязвимость форматирующей строки в реализации библиотеки языка C, поставляемой с некоторыми UNIX-системами. Выявленная уязвимость позволяла злоумышленнику повысить свои права на локальной машине. Подробный отчет о проделанной работе можно найти по адресу www.securityfocus.com/bid/1634.

Multiple CDE Vendor rpc.ttdbserverdISS X-Force обнаружила уязвимость, связанную с неправильным использованием функции syslog() в версиях демона серверной базы данных ToolTalk, поставляемой в нескольких операционных системах с CDE. Благодаря этой уязвимости удаленный злоумышленник, не прошедший аутентификацию, может выполнить произвольный код на атакованном хосте. Подробные сведения по этому вопросу можно найти по адресу www.securityfocus.com/bid/3382.

Классическую удаленную уязвимость форматирующей строки можно найти в версиях программы rwhoisd 1.5.7.1 и более ранних. Она позволяла удаленному злоумышленнику после подключения к серверу выполнить произвольный код. Впервые об уязвимости стало известно благодаря сообщению списка рассылки Bugtraq. Заархивированное сообщение может быть найдено по адресу www.securityfocus.com/archive/1/222756.

Для того чтобы понять уязвимость форматирующей строки программы rwhoisd, следует внимательно изучить ее исходный текст. В главе рассмотрена версия программы 1.5.7.1. На момент написания книги ее можно было загрузить по адресу www.rwhois.net/ftp.

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

Сообщение об ошибке формируется и выводится функцией print_error(). Эта функция вызывается повсюду в исходном тексте программы сервера для обработки ошибок клиента или пользователя. Входными параметрами функции являются номер ошибки в формате целого числа, форматирующая строка и переменное число аргументов.

Исходный текст этой функции может быть найден в файле common/ client_msgs.c (путь указан относительно директории, созданной во время восстановления из архива исходного текста программы версии 1.5.7.1).

/* prints to stdout the error messages. Format: %error ### message

text, where ### follows rfc 640 */

void

print_error(va_alist)

va_dcl

{

va_list list;

int i;

int err_no;

char *format;

if (printed_error_flag)

{

return;

}

va_start(list);

err_no = va_arg(list, int);

for (i = 0; i < N_ERRS; i++)

{

if (errs[i].err_no == err_no)

{

printf(“%%error %s”, errs[i].msg);

break;

}

}

format = va_arg(list, char*);

if (*format)

{

printf(“: ”);

}

vprintf(format, list);

va_end(list);

printf(“\n”);

printed_error_flag = TRUE;

}

В исходном тексте жирным шрифтом отмечено место передачи входных данных программы функции vprintf(). Причиной уязвимости форматирующей строки является не функция vprintf(), а то, как ее используют. Функция print_ error() полагается на то, что вызвавшая ее функция передаст ей правильные входные данные: форматирующую строку и соответствующие ей переменные.

В примере рассматривается функция print_error(), потому что она наглядно демонстрирует причины возникновения уязвимостей форматирующей строки, которые могут быть использованы злоумышленником. Во многих программах есть функции, похожие на print_error(). В некотором смысле функция print_error() подобно функции syslog() служит оболочкой для выдачи диагностики об ошибке. Ее параметрами являются код ошибки и параметры, аналогичные параметрам функции printf(). Как уже обсуждалось в начале главы, проблема состоит в том, что программисты могут забыть о возможности передачи злоумышленником форматирующей строки через входные параметры.

Рассмотрим, что произойдет, когда клиент подключится к сервису и попытается подсунуть функции vprintf () форматирующую строку, взятую из входных параметров функции оболочки print_error().

Те из читателей, которые загрузили исходный текст программы, смогут найти разбираемый фрагмент кода в функции soa_parse_args() из файла с исходным текстом server/soa. Подготовительные действия функции сокращены до минимума. В 53-ей строчке вызывается функция print_error() (строка выделена жирным шрифтом), которая может стать источником серьезных ошибок:

..

auth_area = find_auth_area_by_name(argv[i]);

if (!auth_area)

{

print_error(INVALID_AUTH_AREA, argv[i]);

free_arg_list(argv);

dl_list_destroy(soa_arg);

return NULL;

}

При вызове функции print_error() ей передается параметр argv[i], который является не чем иным, как форматирующей строкой. В конечном счете эта форматирующая строка будет передана функции vprintf() для обработки, как об этом уже предварительно говорилось. Средствам контроля исходного текста программ это место должно показаться очень подозрительным и подходящим для организации атаки. Для безопасной передачи параметров следовало бы вызвать функцию print_error() следующим способом:

print_error(INVALID_AUTH_AREA, «%s», argv[i]);

При этом способе вызова i-й аргумент программы argv[i] передается функции print_error() как переменная, соответствующая спецификации преобразования %s. При этом исключается всякая возможность передачи функции print_error() злонамеренной спецификации преобразования, которая могла бы непредусмотренным образом обработаться функцией vprintf(), вызванной print_error(). Строка argv[i] — это не что иное, как аргумент команды – soa, передаваемой клиентом серверу.

Подводя итог, следует сказать, что когда клиент соединяется с сервером rwhoisd и передает неверную команду – soa, функция print_error() выводит сообщение об ошибке. При этом выполняется следующая последовательность действий.

1. Сервер получает аргумент команды – soa и вызывает для ее обработки функцию soa_directive().

2. Функция soa_directive() передает команду функции soa_parse_args() для обработки.

3. При обнаружении ошибки функция soa_parse_args() передает код ошибки и командную строку функции print_error() в качестве аргументов форматирующей строки.

4. Функция print_error() передает форматирующую строку с содержащимися в ней данными клиента функции vprintf(), о которой уже говорилось, и вызывает ее.

Теперь ясно, что удаленные клиенты могут передать функции vprintf() форматирующую строку, которая является аргументом команды – soa. При подключении к серверу и передаче ему злонамеренной форматирующей строки злоумышленник может записать нужные ему данные в память программы сервера.

Загрузка...