Дэвид Лебланк - 19 смертных грехов, угрожающих безопасности программ
Приложение В. Сводка рекомендаций
В этом приложении сведены наши советы о том, что следует делать, чего не следует, а о чем стоит подумать. Мы решили включить его, потому что иногда разработчику во время написания программы хочется не читать всю книгу, а просто вспомнить, что надо и чего не надо делать.
Грех 1.
Переполнение буфера
Рекомендуется
□ Тщательно проверяйте любой доступ к буферу за счет использования безопасных функций для работы со строками и областями памяти.
□ Пользуйтесь встраиваемыми в компилятор средствами защиты, например флагом /GS и программой ProPolice.
□ Применяйте механизмы защиты от переполнения буфера на уровне операционной системы, например DEP и РаХ.
□ Уясните, какие данные контролирует противник, и обрабатывайте их безопасным образом.
Не рекомендуется
□ Не думайте, что компилятор и ОС все сделают за вас, это всего лишь дополнительные средства защиты.
□ Не используйте небезопасные функции в новых программах.
Стоит подумать
□ Об установке последней версии компилятора C/C++, поскольку разработчики включают в генерируемый код новые механизмы защиты.
□ О постепенном удалении небезопасных функций из старых программ.
□ Об использовании строк и контейнерных классов из библиотеки С++ вместо применения низкоуровневых функций С для работы со строками.
Грех 2.
Ошибки, связанные с форматной строкой
Рекомендуется
□ Пользуйтесь фиксированными форматными строками или считываемыми из заслуживающего доверия источника.
□ Проверяйте корректность всех запросов к локали.
Не рекомендуется
□ Не передавайте поступающие от пользователя форматные строки напрямую функциям форматирования.
Стоит подумать
□ О том, чтобы использовать языки высокого уровня, которые в меньшей степени уязвимы относительно этой ошибки.
Грех 3.
Переполнение целых чисел
Рекомендуется
□ Проверяйте на возможность переполнения все арифметические вычисления, в результате которых определяется размер выделяемой памяти.
□ Проверяйте на возможность переполнения все арифметические вычисления, в результате которых определяются индексы массивов.
□ Пользуйтесь целыми без знака для хранения смещений от начала массива и размеров блоков выделяемой памяти.
Не рекомендуется
□ Не думайте, что ни в каких языках, кроме C/C++, переполнение целого невозможно.
Грех 4.
Внедрение SQL–команд
Рекомендуется
□ Изучите базу данных, с которой работаете. Поддерживаются ли в ней хранимые процедуры? Как выглядит комментарий? Может ли противник получить доступ к расширенной функциональности?
□ Проверяйте корректность входных данных и устанавливайте степень доверия к ним.
□ Используйте параметризованные запросы (также распространены термины «подготовленное предложение» и «связывание параметров») для построения SQL–предложений.
□ Храните информацию о параметрах соединения вне приложения, например в защищенном конфигурационном файле или в реестре Windows.
Не рекомендуется
□ Не ограничивайтесь простой фильтрацией «плохих слов». Существует множество вариантов написания, которые вы не в состоянии обнаружить.
□ Не доверяйте входным данным при построении SQL–предложения.
□ Не используйте конкатенацию строк для построения SQL–предложения даже при вызове хранимых процедур. Хранимые процедуры, конечно, полезны, но решить проблему полностью они не могут.
□ Не используйте конкатенацию строк для построения SQL–предложения внутри хранимых процедур.
□ Не передавайте хранимым процедурам непроверенные параметры.
□ Не ограничивайтесь простым дублированием символов одинарной и двойной кавычки.
□ Не соединяйтесь с базой данных от имени привилегированного пользователя, например sa или root.
□ Не включайте в текст программы имя и пароль пользователя, а также строку соединения.
□ Не сохраняйте конфигурационный файл с параметрами соединения в корне Web–сервера.
Стоит подумать
□ О том, чтобы запретить доступ ко всем пользовательским таблицам в базе данных, разрешив лишь исполнение хранимых процедур. После этого во всех запросах должны использоваться только хранимые процедуры и параметризованные предложения.
Грех 5.
Внедрение команд
Рекомендуется
□ Проверяйте все входные данные до передачи их командному процессору.
□ Если проверка не проходит, обрабатывайте ошибку безопасно.
Не рекомендуется
□ Не передавайте непроверенные входные данные командному процессору, даже если полагаете, что пользователь будет вводить обычные данные.
□ Не применяйте подход «все кроме», если не уверены на сто процентов, что учли все возможности.
Стоит подумать
□ О том, чтобы не использовать регулярные выражения для проверки входных данных; лучше написать простую и понятную процедуру проверки вручную.
Грех 6.
Пренебрежение обработкой ошибок
Рекомендуется
□ Проверяйте значения, возвращаемые любой функцией, относящейся к безопасности.
□ Проверяйте значения, возвращаемые любой функцией, которая изменяет параметры, относящиеся к конкретному пользователю или машине в целом.
□ Всеми силами постарайтесь восстановить нормальную работу программы после ошибки, не допускайте отказа от обслуживания.
Не рекомендуется
□ Не перехватывайте все исключения без веской причины, поскольку таким образом можно замаскировать ошибки в программе.
□ Не допускайте утечки информации не заслуживающим доверия пользователям.
Грех 7.
Кросс–сайтовые сценарии
Рекомендуется
□ Проверяйте корректность всех входных данных, передаваемых Web–приложению.
□ Подвергайте HTML–кодированию любую выводимую информацию, формируемую на основе поступивших входных данных.
Не рекомендуется
□ Не копируйте ввод в вывод без предварительной проверки.
□ Не храните секретные данные в куках.
Стоит подумать
□ Об использовании как можно большего числа дополнительных защитных мер.
Грех 8.
Пренебрежение защитой сетевого трафика
Рекомендуется
□ Пользуйтесь стойкими механизмами аутентификации.
□ Аутентифицируйте все сообщения, отправляемые в сеть вашим приложением.
□ Шифруйте все данные, которые должны быть конфиденциальны. Лучше перестраховаться.
□ Если возможно, передавайте весь трафик по каналу, защищенному SSL/ TLS. Это работает!
Не рекомендуется
□ Не отказывайтесь от шифрования данных из соображений производительности. Шифрование на лету обходится совсем недорого.
□ Не «зашивайте» ключи в код и ни в коем случае не думайте, что XOR с фиксированной строкой можно считать механизмом шифрования.
□ Не игнорируйте вопросы защиты данных в сети.
Стоит подумать
□ Об использовании технологий уровня сети, способных еще уменьшить риск. Речь идет о межсетевых экранах, виртуальных частных сетях (VPN) и балансировании нагрузки.
Грех 9.
Применение загадочных URL и скрытых полей форм
Рекомендуется
□ Проверяйте все данные, поступающие из Web, в том числе и посредством форм, на признаки злоумышленности.
□ Изучите сильные и слабые стороны применяемого вами подхода, если вы не пользуетесь криптографическими примитивами.
Не рекомендуется
□ Не встраивайте конфиденциальные данные в HTTP–заголовки и в HTML–страницы, в том числе в URL, куки и поля форм, если канал не шифруется с помощью таких технологий, как SSL, TLS или IPSec, или данные не защищены криптографическими средствами.
□ Не доверяйте никаким данным в Web–форме, поскольку злоумышленник может легко подставить любые значения вне зависимости от того, используется SSL или нет.
□ Не думайте, что приложение защищено, коль скоро вы применяете криптографию: противник может атаковать систему другими способами. Например, он не станет угадывать случайные числа криптографического качества, а просто попытается подсмотреть их.
Грех 10.
Неправильное применение SSL и TLS
Рекомендуется
□ Пользуйтесь последней версией SSL/TLS. В порядке предпочтительности: TLS 1.1, TLS 1.0hSSL3.
□ Если это имеет смысл, применяйте списки допустимых сертификатов.
□ Прежде чем посылать данные, убедитесь, что сертификат партнера можно проследить до доверенного УЦ и что его срок действия не истек.