Защита от хакеров корпоративных сетей
Шрифт:
Возможность построения произвольных значений целых чисел путем последовательности операций записи – наиболее серьезный способ использования уязвимости форматирующей строки. Он позволяет злоумышленнику полностью контролировать программу, подменяя правильные указатели на указатели злоумышленника. Если злоумышленник воспользуется уязвимостью этим способом, то он сможет, используя программную ошибку атакованной программы, заставить атакованный процесс выполнить нужный ему управляющий программный код.
Что перезаписывать?
Имея возможность использовать любые значения почти в любом месте памяти, перед злоумышленником встает вопрос: «Что перезаписывать?» Обладая возможностью использовать практически любой адрес памяти, у злоумышленника большой выбор. Он может изменить адрес точки возврата функции аналогично тому, как это делается при переполнении буфера. С помощью перезаписи адресов возврата может быть выполнен управляющий программный код злоумышленника. Но в отличие от переполнения буфера злоумышленник не ограничивает себя только подменой адресов возврата.
Перезапись адресов возвратаБольшинство атак переполнения буфера сводятся к перезаписи адреса возврата какой-либо функции на адрес управляющего кода злоумышленника. Модифицированная подобным образом функция в конце своей работы передает управление не в точку возврата, а по подмененному злоумышленником адресу. При переполнении буфера перезаписывается адрес возврата из-за того, что фактически
При перезаписи адресов возврата злоумышленник может столкнуться с двумя проблемами. Одна из них состоит в том, что функция, у которой делается попытка подменить адрес возврата, в конце своей работы не возвращает управление вызвавшей ее функции. При использовании уязвимости форматирующей строки это обычное явление, потому что в большинстве случаев атакуемая функция выдает диагностическое сообщение и после выдачи диагностики инициирует аварийное завершение программы. Другими словами, выводится сообщение об ошибке, возможно, с использованием передаваемых программе данных, которые используются как параметры форматирующей строки, а затем вызывается функция завершения программы exit. В этом случае перезапись адреса возврата для любой функции, кроме printf, ничего не даст. Второй проблемой является то, что перезапись адресов возврата может пресекаться специальными средствами, например StarckGard.
Перезапись указателей таблицы глобальных смещений и указателей на функцииТаблица глобальных смещений (GOT – Global Оffset Table) – это секция в скомпонованной в формате ELF (executable and linkable format – формат исполняемых и компонуемых модулей) программе, в которой хранятся указатели на используемые программой библиотечные функции. Если заменить содержащийся в таблице GOT указатель так, чтобы вместо библиотечной функции он указывал на программный код злоумышленника, то при обращении к библиотечной функции с подмененным указателем будет вызван код злоумышленника.
Не все уязвимые выполнимые файлы, которые злоумышленник может использовать в своих целях, представлены в формате ELF. Прежде всего это касается широко распространенных указателей на функции, которые используются для вызова функций. Указатели функций – определенные в программе переменные, которые слабо защищены от атак злоумышленника. Для того чтобы злоумышленник смог выполнить свою программу, ему необходимо найти в программе вызов функции по ссылке с использованием указателя функции.Пример уязвимой программы
На примере уязвимой программы рассмотрим, каким образом злоумышленник может использовать уязвимости форматирующей строки для достижения своих целей. Наибольший интерес представляют способы удаленного использования уязвимостей форматирующей строки. О степени серьезности уязвимости форматирующей строки можно судить по тому, с какой легкостью злоумышленник может внедриться в сетевой компьютер через Интернет без каких-либо мандатов – учетных записей с параметрами доступа пользователя, сформированными после его успешной аутентификации. Для примера лучше всего рассмотреть уязвимость форматирующей строки в программе широко известного или уважаемого автора, для того чтобы показать, что уязвимости форматирующей строки могут существовать, и существуют, в программах, которые считаются хорошо написанными. Кроме того, пример уязвимой программы должен позволить изучить различные вопросы использования уязвимости форматирующей строки, как, например, вывод отформатированной строки.
В примере рассматривается программа, получившая название rwhoisd. Программа rwhoisd, или демон RWHOIS, является одной из реализаций сервиса RWHOIS. Научно-исследовательское отделение компании Network Solutions, Inc., в настоящее время поддерживает программу rwhoisd сервера RWHOIS, исходные тексты которой доступны по лицензии GNU PublicLicense.
Приоткрывая завесу
Примеры важных уязвимостей форматирующей строки
Кроме упомянутой уязвимости форматирующей строки 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 и более ранних. Она позволяла удаленному
Для того чтобы понять уязвимость форматирующей строки программы 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. При подключении к серверу и передаче ему злонамеренной форматирующей строки злоумышленник может записать нужные ему данные в память программы сервера.Тестирование программ способом случайной форматирующей строки
Поместив в исходный текст программы потенциально уязвимую форматирующую строку, продемонстрируем способы ее использования злоумышленником при помощи входных данных программы и изучим реакцию сервера на них.
В большинстве случаев можно создать такие условия работы программы, когда о наличии в программе уязвимости форматирующей строки можно будет судить по ее поведению. Если уязвимая программа выводит отформатированную строку, то наличие в ней уязвимости форматирующей строки очевидно. При отсутствии вывода о присутствии в программе уязвимости форматирующей строки можно судить по реакции программы на различные спецификации форматов.