Чтение онлайн

на главную - закладки

Жанры

19 смертных грехов, угрожающих безопасности программ

Виега Джон

Шрифт:

Это переполнение интересно тем, что привело к широкому распространению двух весьма разрушительных червей, что повлекло за собой глобальные неприятности в сети Интернет. Переполнялся буфер в куче, доказательством возможности эксплуатации ошибки стало появление очень стабильного червя. Ко всему прочему еще был нарушен принцип предоставления наименьших привилегий, этот интерфейс не должен был быть доступен анонимным пользователям. Интересно еще отметить, что предпринятые в Windows 2003 контрмеры свели последствия атаки к отказу от обслуживания вместо эскалации привилегий. Подробнее об этой проблеме можно прочитать на страницах www.cert.org/ advisories/CA–2003–23.html и www.microsoft.com/technet/security/bulletin/MS03–039.asp.

Искупление греха

Путь

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

Замена опасных функций работы со строками

Как минимум вы должны заменить небезопасные функции типа strcpy, strcat и sprintf их аналогами со счетчиком. Замену можно выбрать несколькими способами. Имейте в виду, что интерфейс старых вариантов функций со счетчиком оставляет желать лучшего, а кроме того, для задания параметров часто приходится заниматься арифметическими вычислениями. В грехе 3 вы увидите, что компьютеры не так хорошо справляются с математикой, как могло бы показаться. Из новых разработок стоит отметить функцию strsafe, Safe CRT (библиотеку времени исполнения для С), которая войдет в состав Microsoft Visual Studio (и очень скоро станет частью стандарта ANSI C/C++), и функции strlcat/strlcpy для *nix. Обращайте внимание на то, как каждая функция обрабатывает конец строки и усечение. Некоторые функции гарантируют, что строка будет завершаться нулем, но большинство старых функций со счетчиком таких гарантий не дают. Опыт группы разработки Microsoft Office по замене небезопасных функций работы со строками в Office 2003 показал, что коэффициент регресии (число новых ошибок в расчете на одно исправление) очень мал, так что пусть страх внести новые ошибки вас не останавливает.

Следите за выделениями памяти

Еще одна причина переполнения буфера – это арифметические ошибки. Прочитайте в грехе 3 о переполнении целых чисел и найдите в своем коде все места, где для вычисления размера буфера производятся арифметические вычисления.

Проверьте циклы и доступ к массивам

Переполнение возможно и в случае, когда неправильно проверяется условие выхода из цикла и не контролируется выход за границы массива перед записью в него. Это одна из самых трудных для обнаружения ошибок; вы увидите, что часто ошибка проявляется совсем не в том модуле, где была допущена.

Пользуйтесь строками в стиле С++, а не С

Это эффективнее простой замены стандартных С–функций, но может повлечь за собой кардинальную переработку кода, особенно если программа собиралась не компилятором С++. Вы должны хорошо представлять себе характеристики производительности STL–контейнеров. Вполне возможно написать очень эффективный код с использованием STL, но, как всегда, нежелание читать руководство (RTFM – Read The Fine Manual) может привести к коду, далекому от оптимального. Наиболее типичное усовершенствование такого рода – переход к использованию шаблонных классов std::string или std::wstring.

Пользуйтесь STL–контейнерами вместо статических массивов

Все вышеупомянутые проблемы относятся и к STL–контейнерам, например vector, но ситуация осложняется еще и тем, что не все реализации класса vector::iterator контролируют выход за границы контейнера. Указанная в заголовке мера может помочь, и автор полагает, что STL способствует быстрому написанию правильного кода, но имейте в виду, что это все же не панацея.

Пользуйтесь инструментами анализа

На рынке появляются прекрасные инструменты для анализа кода на языках C/C++ на предмет нарушения безопасности, в том числе Coverity, PREfast и Kloc–work. В разделе «Другие ресурсы» приведены ссылки. В состав Visual Studio .NET 2005 войдет программа PREfast и еще один инструмент анализа кода под названием Source code Annotation Language (SAL – язык аннотирования исходного текста), позволяющий обнаружить такие дефекты, как переполнение буфера. Проще всего проиллюстрировать SAL на примере. В показанном ниже фрагменте (примитивном) вы знаете, как соотносятся аргументы data и count: длина data составляет count

байтов. Но компилятору об этом ничего не известно, он видит только типы char * and a size_t.

...

void *DoStuff(char *data, size_t count) {

static char buf[32];

return memcpy(buf, data, count);

}

На первый взгляд, код не содержит ничего плохого (если не считать, что мы возвращаем указатель на статический буфер, ну посмейтесь над нами). Однако если count больше 32, то возникает переполнение буфера. Если бы этот код был аннотирован с помощью SAL, то компилятор мог бы отловить эту ошибку:

...

void *DoStuff(__in_ecount(count) char *data, size_t count) {

static char buf[32];

return memcpy(buf, data, count);

}

Объясняется это тем, что теперь компилятор и/или PREfast знают о тесной связи аргументов data и count.

Дополнительные защитные меры

Дополнительные защитные меры – это как ремни безопасности в автомобиле. Часто они смягчают последствия столкновения, но в аварию попадать все равно не стоит. Важно понимать, что для всех основных способов минимизировать эффект от переполнения буфера условия, которые приводят к переполнению буфера, продолжают существовать, поэтому достаточно изощренная атака может обойти ваши контрмеры. Все же рассмотрим некоторые подходы.

Защита стека

Защиту стека первым применил Криспин Коуэн в своей программе Stack–guard, затем она была независимо реализована Microsoft с помощью флага компилятора /GS. В самом простом варианте суть ее состоит в том, что в стек между локальными переменными и адресом возврата записывается некое значение. В более современных реализациях для повышения эффективности может также изменяться порядок переменных. Достоинство этого подхода в том, что он легко реализуется и почти не снижает производительности, а кроме того, облегчает отладку в случае порчи стека. Другой пример – это программа ProPolice, созданная компанией IBM как расширение компилятора Gnu Compiler Collection (GCC). Любой современный продукт должен включать в себя защиту стека.

Запрет исполнения в стеке и куче

Эта контрмера существенно усложняет задачу хакера, но может сказаться на совместимости. Некоторые приложения считают допустимым компилировать и исполнять код на лету. Например, это относится к языкам Java и С#. Важно также отметить, что если противник сумеет заставить ваше приложение пасть жертвой атаки с возвратом в libc, когда для достижения неблаговидных целей выполняется вызов стандартной функции, то он сможет снять защиту со страницы памяти.

К сожалению, современная аппаратура по большей части не поддерживает эту возможность, а имеющаяся подержка зависит от процессора, операционной системы и даже ее конкретной версии. Поэтому рассчитывать на наличие такой защиты в реальных условиях не стоит, но все равно следует протестировать свою программу и убедиться, что она будет работать, когда стек и куча защищены от исполнения. Для этого нужно запустить ее на том процессоре и операционной системе, которые поддерживают аппаратную защиту. Например, если целевой платформой является Windows ХР, то прогоните тесты на машине с процессором AMD Athlon 64 FX под управлением Windows ХР SP2. В Windows эта технология называется Data Execution Protection (DEP – защита от исполнения данных), а раньше носила имя No eXecute (NX).

ОС Windows Server 2003 SP1 также поддерживает эту возможность, равно как подсистема РаХ для Linux и OpenBSD.

Другие ресурсы

□ Writing Secure Code, Second Edition by Michael Howard and David C. LeBlanc (Microsoft Press, 2002), Chapter 5, «Public Enemy #1: Buffer Overruns»

□ «Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft Windows Server 2003» by David Litchfield: www.ngssoftware.com/papers/ defeating–w2k3–stack–protection.pdf

Поделиться:
Популярные книги

Sos! Мой босс кровосос!

Юнина Наталья
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Sos! Мой босс кровосос!

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Я – Орк

Лисицин Евгений
1. Я — Орк
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я – Орк

Купеческая дочь замуж не желает

Шах Ольга
Фантастика:
фэнтези
6.89
рейтинг книги
Купеческая дочь замуж не желает

Возвышение Меркурия. Книга 4

Кронос Александр
4. Меркурий
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Возвышение Меркурия. Книга 4

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

Наследник и новый Новосиб

Тарс Элиан
7. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник и новый Новосиб

Законы Рода. Том 4

Flow Ascold
4. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 4

Промышленникъ

Кулаков Алексей Иванович
3. Александр Агренев
Приключения:
исторические приключения
9.13
рейтинг книги
Промышленникъ

Адъютант

Демиров Леонид
2. Мания крафта
Фантастика:
фэнтези
6.43
рейтинг книги
Адъютант

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Измена. Не прощу

Леманн Анастасия
1. Измены
Любовные романы:
современные любовные романы
4.00
рейтинг книги
Измена. Не прощу

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый