Разработка защищенных программ

Разработка защищенных программ

Несколько месяцев назад Билл Гейтс объявил, что безопасность станет приоритетом номер 1 в Microsoft. Несколько групп в Microsoft, такие как Trusted Computing Group и Secure Windows Initiative стремятся улучшить безопасность в продуктах Microsoft, и, в конечном счете, улучшить ситуацию для людей и корпораций во всем мире. Если Microsoft, с ее миллиардными ресурсами и многочисленным штатом сотрудников, имеет проблемы с безопасностью, то как же решать проблему создания доверенных систем?

Михаил Разумов

Создание защищенных систем.

Несколько месяцев назад Билл Гейтс объявил, что безопасность станет приоритетом номер 1 в Microsoft. Несколько групп в Microsoft, такие как Trusted Computing Group и Secure Windows Initiative стремятся улучшить безопасность в продуктах Microsoft, и, в конечном счете, улучшить ситуацию для людей и корпораций во всем мире. Эта инициатива не удивительна, принимая во внимание многочисленные уязвимости, найденные недавно в Windows XP, Internet Information Server, Internet Explorer и Outlook. Из-за популярности продуктов Microsoft и их значительной доли на рынке, уязвимости вызвали значительный ущерб повсеместно в Интернет. Если Microsoft, с ее миллиардными ресурсами и многочисленным штатом сотрудников, имеет все эти проблемы с безопасностью, то как же решать проблему создания доверенных систем?

Как скажет вам любой хороший профессионал по безопасности, невозможно создать полностью безошибочное и неуязвимое программное обеспечение. Ресурсы и финансы, требуемые для создания такого программного обеспечения, будут бесконечны. Основная идея в индустрии безопасности – уменьшение риска. То есть, уменьшение риска до приемлемого уровня. Эта статья содержит краткий обзор некоторых ключевых вопросов защищенного программирования. В ней показаны некоторые типичные ошибки, совершаемые при создании программ, которые ведут к их уязвимости. Далее представлен список рекомендаций, неукоснительное следование которым поможет избежать 90% проблем безопасности. И, в завершение – список ресурсов, которые помогут вам в задаче создания более защищенного программного обеспечения.

Защищенное программирование. Типичные ошибки

Разработка защищенных программ – процесс, требующий повышенного внимания на всех стадиях и уровнях. Это означает строгие требования безопасности, отличное понимание проблем защищенности и наличие группы оценки качества, которая может обнаруживать проблемы безопасности. Однако, чтобы решить эту проблему, нужно много учиться, и даже при этом, нельзя решить все проблемы безопасности одновременно. Существует пять основных проблем, которые охватывают 90% уязвимостей программного обеспечения. Если вы учтете их, вы сможете на порядок увеличить защищенность ваших программ.

Переполнение буфера

Переполнение буфера – пожалуй, наиболее часто используемая хакерами ошибка программирования. Подробности того, как переполнение буфера может быть использовано для запуска произвольного кода, не входят в тему этой статьи, но вы легко найдете множество материала по данной теме (в частности, и на securitylab.ru). Достаточно сказать, что если программа удаленно подвержена переполнению буфера, хакер может получить полный контроль над системой. Первичная причина этой проблемы в том, что для вводимой информации используются статичные, фиксированного размера переменные, и злоумышленник может превысить размер отведенного под переменную буфера.

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

Написание эксплоита для атаки с использованием переполнения буфера часто считается «черной магией», так как требует огромного опыта и знания операционных систем, компиляторов, ассемблера. В итоге, многие люди ошибочно полагают, что если так сложно определить и атаковать эту уязвимость, то существующий риск минимальный. Однако, даже самый беглый поиск по нескольким популярным сайтам, посвященным безопасности, даст ссылки на множество эксплоитов для практически всех коммерческих программ. Самый неопытный хакер, и то может просто скачать программу и совершить взлом, даже не задумываясь, как автор программы-эксплоита обнаружил и взломал переполнение буфера. Действительно, как это происходит?

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

Уязвимости форматной строки

Уязвимости форматной строки – новый класс проблем безопасности, обнаруженный в последние пару лет. Форматные строки – это программные конструкции, используемые в языках C и C++ для форматирования ввода-вывода. Они содержат специальные идентификаторы (такие как %s для строк, %d для целых чисел), которые, в случае использования в злонамеренном вводе, могут открыть информацию о содержании стэка и используемых в функции переменных. В частности, опасный идентификатор %n может использоваться для изменения данных в памяти. Поскольку это позволяет хакерам делать почти то же, что и при переполнении буфера, результаты одинаковы: запуск произвольного кода.

Первичная причина уязвимости форматной строки в использовании функций переменного параметра в C/C++. Эту проблему можно решить с помощью проверки на правильность ввода и поиска ошибок в коде. Также можно использовать автоматические утилиты проверки кода для обнаружения ошибок типа: printf (string); будет рекомендовано заменить на printf (“%s”, string).

Аутентификация

Аутентификация – наиболее важный компонент в любой защищенной системе. Некорректная аутентификация пользователя сделает все остальные функции безопасности, такие как шифрование, аудит и авторизация, просто бесполезными. Наиболее типичная ошибка в аутентификации – использование слабых мандатов (credentials), что позволяет хакеру применить метод грубой силы (brute force), например, к взлому пароля. Кроме того, необходима строгая политика паролей для уменьшения вероятности их взлома. Требования к составу пароля зависят от уровня безопасности, требуемого приложением и его функциями. Обычно рекомендуется, чтобы пароли были длиной минимум в 8 символов и включали буквы, цифры и спецсимволы.

Многие приложения, особенно Web-приложения, используют аутентификаторы для определения зарегистрировавшегося пользователя. Аутентификаторы – это как «билеты», которые выдаются после ввода пользователем аутентификационной информации. Эти «билеты» могут использоваться для проверки подлинности в течение сессии вместо запроса имени пользователя и пароля. В Web-приложениях аутентификаторы часто сохраняются в куки (cookies). При создании приложения важно убедиться, что аутентификаторы не подвержены атакам грубой силы или предсказания.

Авторизация

Авторизация – это процесс разрешения или запрета доступа к определенному ресурсу, основанный на идентификации аутентификационной информации. Уязвимости авторизации являются типичными проблемами во многих приложениях. Наиболее частые ошибки:

  • Авторизация проведена некорректно. Интерфейс обеспечивает доступ к ресурсу до тех пор, пока обеспечивается аутентификация. Обычно, в этом случае требуется некий идентификатор, и предполагается, что он не может быть угадан или изменен. Например, в одном банковском Web-приложении Web-сервер устанавливал переменную в Javascript в номер аккаунта. Простым изменением этой переменной стало возможно просматривать и изменять другие аккаунты.
  • Слишком много доверия к пользовательскому вводу. Например, HTTP куки – это один из типов пользовательского ввода в Web-приложение, который может быть изменен. Если приложение осуществляет авторизацию с помощью куки, оно может довериться фальсифицированной информации. Это может быть или имя пользователя, или запрашиваемый ресурс. Например, при испытании одного приложения была найдена переменная в куки с именем “admin”. Если она устанавливалась в “true”, приложение предоставляло нелегитимному пользователю администраторские права.
  • Ошибки канонизации. Часто приложения принимают решения об авторизации на основе аутентификационной информации и запрошенных ресурсов. Многие уязвимости безопасности относятся к ошибкам канонизации в имени ресурса. Например, хотя приложение может запретить доступ к \secure\secret.txt, оно может дать доступ к \public\..\secure\secret.txt на основании имени директории. Кодировки в Юникод и в шестнадцатеричном формате относятся к той же категории.

Криптография

Если криптография производится в приложении, чувствительность данных очень высока. Опытных программистов, имеющих полное математическое понимание криптографических алгоритмов, как это ни странно и печально, очень мало. Одна ошибка в разработке криптографического алгоритма или его реализации может полностью подорвать защищенность приложения. Многие программы используют алгоритмы промышленного стандарта, такие как RSA или blowfish, но не некорректно работают с памятью, что оставляет возможным кражу пароля и других данных в чистом виде. Очень рекомендуется использовать CryptoAPI и CAPICOM, встроенные в операционные системы Windows, или купить библиотеки третьих лиц для избежания проблем с использованием криптографии. Очень легко по ошибке попасть в ловушку, считая, что данные «выглядят» зашифровано, и потому защищены.

Рекомендации для разработки защищенных программ

К этому моменту вы, если вы являетесь разработчиком программ, уже можете задаться вопросом - при всех этих потенциальных проблемах как мне определить, не имеет ли моя программа какие-то уязвимости? Более того, если имеет, то как мне решить их? Ответ на первый вопрос прост. Проведите аудиты и тесты безопасности и анализ кода для определения уязвимостей безопасности в приложении. Ответ на второй вопрос гораздо сложнее. Создание защищенного программного обеспечения является проблемой, которую пытались разрешить многие люди в течение долгого времени. Вы не найдете здесь ответа, но найдете список рекомендаций, которые, как мы ми говорили, помогут вам избежать 90% типичных уязвимостей безопасности.

Не доверяйте пользовательскому вводу

Хакер зачастую атакует приложение через его внешние интерфейсы. Примеры внешних интерфейсов: сокеты, Web-формы, ввод командной строки, файлы и т.п. Многие эксплоиты посылают злонамеренные входные данные, чтобы заставить приложение вести себя непредусмотренным образом, например как при переполнении буфера. Хотя это и кажется легким, но распознавание всего ввода не всегда может оказаться таким уж простым. Например, в Web-приложении наиболее типичный пользовательский ввод – URI и данные для форм. Однако, хакер, который не использует стандартный Web-броузер, может манипулировать HTTP заголовками, куки, и скрытыми данными. Эти типы входных данных никогда не следует считать содержащими безопасные данные.

Проверка правильности ввода

Необходимо разработать описание достоверных данных для каждого ввода. Пример для случая аутентификации: имя пользователя должно содержать буквы и цифры, быть длиной 6-20 символов, и пароль должен содержать 6-20 печатаемых символов. Если клиент посылает переполнение буфера более 20 символов, приложение должно отсоединить пользователя. Если производится атака SQL injection, проверка запроса в приложении не должна пропустить его к SQL серверу. Такое недоверие к пользовательскому воду в комбинации с хорошей проверкой корректности ввода в корне предотвратит большинство атак. Ваше приложение может иметь уязвимости SQL injection и переполнения буфера, но при правильной проверке корректности ввода оно может стать невзламываемым для подобных атак.

«Магические» ключи

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

  • VCC /G – Visual Studio .NET имеет опцию /G, которая добавляет автоматическую проверку границ для предотвращения переполнения буфера. Имейте в виду, что существуют техники для обхода автоматической проверки границ. Тем не менее, это делает гораздо более сложным для хакеров взлом переполнением буфера и облегчает  для вас определение уязвимости.
  • midl /robust – Использование ключа /robust с компилятором midl дает жесткую проверку параметров в RPC приложениях.
  • DCOM encryption – Включает шифрование пакетов для DCOM приложений.
  • Avoid using Null DACLS – никогда не используйте NULL DACLS (Discretionary Access Control Lists) в приложении.

Ресурсы для написания защищенных программ

Утилиты

Здесь представлены утилиты, осуществляющие автоматический анализ программного кода и определяющие недостатки в нем. Достоинство автоматизированных утилит в том, что они требуют минимальной от вас работы. Не самые опытные разработчики могут запустить эти утилиты, проанализировать полученные результаты и исправить ошибки. Кроме того, каждая из перечисленных ниже утилит имеет большую базу данных проблем защиты и могут распознать уязвимости, о которых разработчик может и не подозревать. Автоматизированные утилиты могут также анализировать огромное количество программного кода за небольшое время. Но, как и с любой утилитой, необходимо знать их ограничения. Они производят очень подробный вывод, с большим количеством ложных тревог, и необходимо много времени, чтобы все это проанализировать. Кроме того, автоматизированные системы прекрасно работают с проблемами типа переполнения буфера, но не прослеживают логику вашей программы и не определяют, авторизован ресурс, или нет. Вообще, уязвимости аутентификации и авторизации плохо поддаются автоматическому анализу. Таким образом, рекомендуется использовать автоматизированные системы для поиска уязвимостей, типа переполнения буфера или некорректного ввода. А затем уже передавать исправленный код на проверку профессионалам безопасности для отслеживания проблем аутентификации, авторизации и шифрования. Некоторые утилиты, которые могут помочь вам в этом:

Заключение

Разработка защищеннго программного обеспечения – непростая задача. Но, принимая во внимание количество атак сегодня, было бы преступной халатностью не создавать защищенный от хакеров код. Затраты, требуемые для создания защищенных программ, очень высоки. Тем не менее, обучая программистов избегать типичных ошибок, проводя анализ безопасности кода и проверку приложений на наличие ошибок безопасности, можно значительно улучшить код и избавиться от большинства типичных на сегодняшний день уязвимостей.

Большой брат следит за вами, но мы знаем, как остановить его

Подпишитесь на наш канал!