Дэвид Лебланк - 19 смертных грехов, угрожающих безопасности программ

Все авторские права соблюдены. Напишите нам, если Вы не согласны.
Описание книги "19 смертных грехов, угрожающих безопасности программ"
Описание и краткое содержание "19 смертных грехов, угрожающих безопасности программ" читать бесплатно онлайн.
Эта книга необходима всем разработчикам программного обеспечения, независимо от платформы, языка или вида приложений. В ней рассмотрены 19 грехов, угрожающих безопасности программ, и показано, как от них избавиться. Рассмотрены уязвимости на языках C/C++, C#, Java, Visual Basic, Visual Basic.NET, Perl, Python в операционных системах Windows, Unix, Linux, Mac OS, Novell Netware. Авторы издания, Майкл Ховард и Дэвид Лебланк, обучают программистов, как писать безопасный код в компании Microsoft. На различных примерах продемонстрированы как сами ошибки, так и способы их исправления и защиты от них. Если вы программист, то вам просто необходимо прочесть эту книгу.
Перевод: А. Слинкин
}
В данном примере приведение а + b от int к byte возбуждает исключение. В следующей строке, где вызывается Convert.ToByte, исключение возникло бы и без ключевого слова checked, но его наличие приводит к возбуждению исключения еще и при вычислении аргументов метода Console.Write(). Поскольку иногда переполнение целого допускается намеренно, то имеется также ключевое слово unchecked, отключающее контроль на переполнение.
Слова checked и unchecked можно также использовать для включения или отключения контроля в одном выражении:
...checked (с = (byte) (Ь + а));
И наконец, включить контроль можно с помощью флага /checked компилятора. Если этот флаг присутствует, то нужно явно помечать словом unchecked участки кода или отдельные предложения, в которых переполнение допустимо.
Греховность Visual Basic и Visual Basic .NET
Visual Basic регулярно претерпевает кардинальные модификации, а переход от Visual Basic 6.0 к Visual Basic .NET стал самым значительным шагом со времен введения объектной ориентированности в Visual Basic 3.0. Одно из самых фундаментальных изменений связано с целочисленными типами (см. табл. 3.1).
Вообще говоря, и Visual Basic 6.0, и Visual Basic .NET не подвержены угрозе исполнения произвольного кода из–за переполнения целых чисел. В Visual Basic 6.0 генерируется ошибка, если при выполнении какого–либо оператора или функции преобразования, например CInt(), возникает переполнение. В Visual Basic .NET в этом случае возбуждается исключение типа System.OverflowException. Как показано в табл. 3.1, программа на Visual Basic .NET имеет доступ ко всем целочисленным типам, определенным в каркасе .NET Framework.
Таблица 3.1. Целочисленные типы, поддерживаемые Visual Basic 6.0 и Visual Basic .NET
Хотя операции в самом языке Visual Basic, может быть, и неуязвимы для переполнения целого, но потенциальная проблема состоит в том, что вызовы Win32 API обычно принимают в качестве параметров 32–разрядные целые без знака (DWORD). Если ваша программа передает системному вызову 32–разрядное целое со знаком, то в ответ может получить отрицательное число. Аналогично вполне допустимо выполнить такую операцию, как 2 – 8046, над числами со знаком, но что, если указать в качестве одного из операндов такое число без знака, чтобы возникло переполнение? Если системный вызов возвращает некоторое значение, а потом вы выполняете манипуляции над этим значением и величиной, прямо или косвенно (после тех или иных вычислений) полученной от пользователя, и напоследок обращаетесь к другим системным вызовам, то можете оказаться в угрожаемой ситуации. Переходы от знаковых чисел к беззнаковым и обратно чреваты опасностью. Даже если переполнение целого и не приведет к исполнению произвольного кода, необработанные исключения станут причиной отказа от обслуживания. Неработающее приложение не приносит доходов заказчику.
Греховность Java
В отличие от Visual Basic и С#, в язык Java не встроена защита от переполнений. Вот цитата из спецификации языка «Java Language Specification*, размещенной по адресу http://java.sun.com/docs/books/jls/second_edition/html/typeValues.doc.html#9151:При выполнении встроенных операций над целыми типами переполнение или потеря значимости не индицируются. Единственные арифметические операторы, которые могут возбудить исключение (§11), – это оператор целочисленного деления / (§15.17.2) и оператор вычисления остатка % (§15.17.3). Они возбуждают исключение ArithmeticException, если правый операнд равен нулю.
В отличие от Visual Basic, Java поддерживает лишь подмножество всего диапазона целочисленных типов. Хотя 64–разрядные целые поддерживаются, но единственным беззнаковым типом является char, и он представляется в виде 16–разрядного значения без знака.
Поскольку в Java есть только знаковые типы, проверка переполнения становится непростым делом, и по сравнению с C/C++ удается лишь избежать затруднений, связанных со смешанными операциями над знаковыми и беззнаковыми величинами.
Греховность Perl
По крайней мере, два автора этой книги являются горячими сторонниками Perl. Но, несмотря на это, следует признать, что работа с целыми числами реализована в Perl странно. Внутри они представляются в виде чисел с плавающей точкой двойной точности, но тестирование позволяет выявить некоторые любопытные вещи. Рассмотрим следующий код:...$h = 4294967295;
$i = 0xffffffff;
$k = 0x80000000;
print "$h = 4294967295 – $h + 1 = ".($h + 1)."\n";
print "$i = 0xffffffff – $i + 1 = ".($i + 1)."\n";
printf("\nИспользуется printf со спецификатором %%d\n");
printf("\\$i = %d, \$i + 1 = %d\n\n", $i, $i + 1);
printf("\nТестируется граничный случай деления\n");
printf("0x80000000/-1 = %d\n", $k/-1);
print "0x80000000/-1 = ".($k/-1)."\n";
В результате печатается следующее:
...[e:\projects\19_sins\perl foo.pl
4294967295 = 4294967295 – 4294967295 + 1 = 4294967296
4294967295 = 0xffffffff – 4294967295 + 1 = 4294967296
Используется printf со спецификатором %d
$i = -1, $i + 1 = -1
Тестируется граничный случай деления
0x80000000/-1 = -2147483648
0x80000000/-1 = -2147483648
На первый взгляд, результат выглядит странно, особенно когда используется printf с форматной строкой (в отличие от обычной функции print). Первым делом в глаза бросается то, что мы можем присвоить переменной максимально возможное значение без знака, но после прибавления к нему 1 она либо увеличивается на единицу, либо – если печатать с помощью %d – вообще не изменяется. Загвоздка в том, что на самом деле вы оперируете числами с плавающей точкой, а спецификатор %d заставляет Perl преобразовать double в int. В действительности никакого переполнения нет, но при печати результатов создается впечатление, будто оно произошло.
В силу особенностей работы с числами в Perl мы рекомендуем быть очень осторожными при написании на этом языке приложений, в которых много математических операций. Если вы не разбираетесь досконально в арифметике с плавающей точкой, то можете столкнуться с весьма поучительными сюрпризами. Другие языки высокого уровня, например Visual Basic, тоже иногда производят преобразования в числа с плавающей точкой. Следующий код иллюстрирует, что в таком случае происходит:
...print (5/4)."\n";
1.25
Для большинства обычных приложений Perl ведет себя предсказуемо и работает великолепно. Но не забывайте, что вы имеете дело не с целыми числами, а с числами с плавающей точкой, – а это «две большие разницы».
Где искать ошибку
Любое приложение, в котором производятся арифметические операции, подвержено этому греху, особенно когда некоторые входные данные поступают от пользователя и их правильность не проверяется. Особое внимание обращайте на вычисление индексов массивов и размеров выделяемых буферов в программах на C/C++.
Выявление ошибки на этапе анализа кода
При написании программ на языках C/C++ надо обращать самое пристальное внимание на возможность переполнения целого числа. Теперь, когда многие разработчики осознали важность проверок размеров при прямых манипуляциях с памятью, атаки направлены нате арифметические операции, с помощью которых эти проверки выполняются. Следующими на очереди стоят С# и Java. Прямые манипуляции с памятью в этих языках запрещены, но тем не менее можно допустить почти все ошибки, которые характерны для С и С++.
Ко всем языкам относится следующее замечание: проверяйте входные данные прежде, чем каким–либо образом их использовать! В Web–серверах Microsoft IIS 4.0 и 5.0 очень серьезная ошибка имела место из–за того, что программист сначала прибавил к переменной 1, а затем проверил, не оказался ли размер слишком большим. При тех типах, что он использовал, 64К–1 + 1 оказалось равно нулю! На соответствующее извещение есть ссылка в разделе «Другие ресурсы».
C/C++
Первым делом найдите все места, где выделяется память. Самое опасное – это выделение блока, размер которого вычисляется. Убедитесь, что при этом невозможно переполнение целого. Далее обратите внимание на функции, которые получают входные данные. Автор как–то встретил примерно такой код:
...THING* AllocThings(int a, int b, int c, int d)
{
int bufsize;
THING* ptr;
bufsize = IntegerOverflowsRUs(a, b, c, d);
ptr = (THING*)malloc(bufsize);
return ptr;
}
Ошибка скрывалась в функции, вычисляющей размер буфера, к тому же найти ее мешали загадочные, ничего не говорящие читателю имена переменных (и литералов, которые представлены типом signed int). Если у вас есть время на доскональный анализ, проследите порядок вызова всех ваших функций вплоть до обращений к низкоуровневым библиотечным функциям или системным вызовам. И напоследок выясните, откуда поступают данные. Можете ли вы утверждать, что аргументы функций не подвергались манипуляциям? Кто контролирует аргументы: вы или потенциальный противник?
По мнению автора языка Perl, величайшим достоинством программиста является лень! Так давайте пойдем простым путем – заставим потрудиться компилятор. Включите уровень диагностики /W4 (для Visual С++) или–Wall либо–Wsign–compare (для gcc) – и вы увидите, как много в вашей программе мест, где возможны проблемы с целыми числами. Обращайте внимание на все предупреждения, касающиеся целых чисел, особенно на те, в которых говорится о сравнении знаковых и беззнаковых величин, а также об усечении.
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!
Похожие книги на "19 смертных грехов, угрожающих безопасности программ"
Книги похожие на "19 смертных грехов, угрожающих безопасности программ" читать онлайн или скачать бесплатно полные версии.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Отзывы о "Дэвид Лебланк - 19 смертных грехов, угрожающих безопасности программ"
Отзывы читателей о книге "19 смертных грехов, угрожающих безопасности программ", комментарии и мнения людей о произведении.