суббота, 8 января 2011 г.

ISSP \ Домен 09. Безопасность приложений. Часть 1

В этой части рассмотрены следующие вопросы:
  • Важность программного обеспечения
  • Где нужно размещать безопасность?
  • Различные среды имеют различные потребности в обеспечении безопасности
  • Среда и приложения
  • Безопасность и функциональность
  • Типы, форматы и размер данных
  • Проблемы внедрения приложений и использования настроек «по умолчанию»
  • Сбои и ошибки в приложениях

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


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

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


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

В действительности, первопричиной большинства уязвимостей являются недостатки самого программного обеспечения. Ниже приведены несколько основных причин, поясняющих, почему сейчас чаще используются средства защиты периметра, а не обеспечение безопасности при разработке программного обеспечения:
  • В прошлом, при разработке программного обеспечения не уделялось внимания вопросам безопасности, поскольку не было такой потребности. Из-за этого и сейчас многие программисты не задумываются о вопросах безопасности и не используют методы безопасного программирования
  • Большинство специалистов по безопасности не являются разработчиками программного обеспечения
  • Многие разработчики программного обеспечения, не уделяют достаточного внимания вопросам безопасности
  • Производители программного обеспечения стараются как можно быстрее вывести свои продукты на рынок, говоря в первую очередь об их функциональности, но не о безопасности
  • Компьютерное сообщество привыкло получать программное обеспечение с ошибками, а затем применять патчи
  • Покупатели программного обеспечения не могут контролировать недостатки в нем, поэтому они вынуждены обеспечивать защиту периметра
Концентрация внимания на функциональности и принятие быстрых решений оказывают негативное влияние на современном этапе компьютерной эволюции. Двадцать лет назад, когда использовались мейнфреймы, много безопасности не требовалось, т.к. лишь немногие люди знали, как они работают, а пользователи использовали для доступа к ним простые терминалы, посредством которых нельзя было ввести вредоносный код в мейнфрейм, среда была закрытой. Большинство протоколов и платформ, которые мы используем сейчас, были разработаны в те времена, когда угрозы и атаки не были распространены, и строгие меры безопасности не были нужны. Однако с тех пор эволюция компьютеров и программного обеспечения продвинулась очень далеко. Высокий спрос на компьютерные технологии и различное программное обеспечение повысил спрос на программистов, проектировщиков систем, администраторов и инженеров. Спрос на таких специалистов стал очень большим, что привело в эту отрасль целую волну людей, не имевших достаточного опыта. Недостаток опыта, быстрое изменение технологий, а также рыночные гонки, добавили проблем с обеспечением безопасности, необходимость в которой не всегда понимали.

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

В этом Домене мы сделаем попытку показать, как учесть вопросы безопасности в самом программном обеспечении и процессе его разработки. Это требует перехода от реактивного к проактивному подходу при решении проблем безопасности, чтобы избежать этих проблем или, по крайней мере, минимизировать их количество. На Рисунке 9-1 показан применяемый в настоящее время способ решения проблем безопасности.

Рисунок 9-1. Традиционный процесс выпуска программного обеспечения на рынок и обеспечения его безопасности


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

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

Времена, когда компании разрабатывали простые веб-страницы и размещали их в Интернете для иллюстрации своей продукции и услуг, давно прошли. Сегодня компании разрабатывают сложные и функциональные веб-приложения, имеющие трехзвенную архитектуру и работающие с использованием промежуточного программного обеспечения. Сложность сетей и приложений постоянно растет, отслеживание ошибок и нарушений безопасности в них становится очень сложной задачей.
Модель клиент/сервер. Архитектура клиент/сервер позволяет создавать прикладные системы, разделенные между несколькими платформами, использующими различные операционные системы и аппаратные средства. Клиентская часть запрашивает определенные сервисы, а серверная часть выполняет эти запросы. Сервер выполняет обработку данных и возвращает клиенту результаты обработки. Клиентская часть реализует интерфейсные элементы приложения и взаимодействует с пользователем, а серверная часть выполняет всю фоновую обработку, которая, как правило, является наиболее трудоемкой.

Программные средства безопасности могут быть реализованы в операционной системе, приложении или в системе управления базами данных (СУБД). Как правило, средства безопасности реализуются на всех указанных уровнях и используются совместно, дополняя друг друга. Каждый уровень имеет свои сильные и слабые стороны, но если все они хорошо изучены, правильно настроены и работают согласованно, можно избежать многих сценариев и разновидностей нарушения безопасности. Однако во многих случаях полагаются только на средства безопасности, реализованные в операционной системе. Такой подход имеет существенный минус, поскольку операционная система может эффективно контролировать, управлять и ограничивать доступ субъекта только к объектам в рамках самой операционной системы, но она далеко не всегда может делать это в приложениях. Если в программном коде приложения существуют недостатки в обеспечении безопасности, на уровне операционной системы крайне сложно будет реализовать эффективную защиту от компрометации приложения посредством этой уязвимости. Операционная система – это среда для работы приложений, не следует ожидать от нее учета всех нюансов работы различных приложений и реализованных в них механизмов.

С другой стороны, средства безопасности, реализованные в приложениях и СУБД, являются очень специфическими и могут обеспечить защиту только в рамках самих этих приложений и СУБД. Приложение может обеспечить защиту данных, разрешив выполнять ввод информации только определенным образом, ограничивая доступ пользователей к данным, хранящимся в критичных областях базы данных и т.д. Но оно не может запретить пользователю записывать фиктивные данные в таблицу ARP (Address Resolution Protocol), т.к. за работу этой таблицы отвечает операционная система и ее сетевой стек. У средств безопасности операционной системы и приложения есть свое место и свои ограничения. Основная задача заключается в том, чтобы понять, где заканчивается область действия одних средств безопасности, чтобы настроить и ввести в действие другие средства безопасности.

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


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

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

В большинстве приложений осуществляется обмен данными между различными частями программы, обмен данными с другими программами, с операционной системой, принимаются введенные пользователями данные. Каждый из маршрутов передачи (ввода) данных должен быть учтен, нужно проанализировать и протестировать каждый возможный сценарий взаимодействия, каждый вариант ввода данных. Только такой подход сможет обеспечить реально высокое качество приложения. Важно, чтобы была обеспечена возможность тестирования каждого модуля в отдельности, а также различных модулей при их взаимодействии между собой. Столь глубокий анализ и тестирование позволят сделать продукт более безопасным, заранее выявив недостатки, которые могут быть использованы злоумышленниками в дальнейшем.


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

Мы рассматривали переполнение буфера в Домене 03 и говорили, что такая атака может быть осуществлена в случае, если программный код не проверяет фактическую длину принимаемых входных данных. Специально подготовленные атакующим данные, в действительности содержащие команды, могут переполнить выделенный для них буфер, что позволит этим командам выполниться в привилегированном режиме и даст атакующему возможность получить контроль над системой. Если программист пишет программу, которая ожидает входящие данные, объемом не более 5KB, он должен правильно реализовать это в коде, выделив для хранения данных буфер необходимого объема и предусмотрев функцию проверки объема реально полученных данных. Даже если атакующий передаст этой программе более 5КВ данных, программа должна автоматически отбросить лишние данные. Иначе атакующий может отправить 5KB данных и прибавить к ним еще 50KB кода, содержащего вредоносные команды, которые будут обработаны процессором.

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

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

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


Как многие знают, большинство приложений по умолчанию устанавливаются с настройками, которые, как правило, далеко не безопасны. После установки программы нужно включить и настроить функции безопасности. Например, в отношении безопасности Windows NT было высказано не мало критики, однако эта система может быть настроена для обеспечения безопасности многими различными способами. Просто сразу после установки механизмы безопасности в ней не настроены. Это связано с тем, что настройки безопасности тесно связаны с особенностями среды, в которую интегрируется система, а также с тем, что такой подход обеспечивает более «дружеский» процесс установки системы. Представьте, что вы установили новый продукт, который при дальнейших попытках настройки для интеграции с другими приложениями постоянно выдает сообщение «Доступ запрещен».

При установке программного или аппаратного продукта безопасности, по умолчанию должны устанавливаться права «Нет доступа». Например, если администратор устанавливает новый межсетевой экран с пакетной фильтрацией, он не должен разрешать передачу никаких сетевых пакетов до тех пор, пока администратор специально не предусмотрел соответствующее разрешение в правилах межсетевого экрана. Однако это требует, чтобы администратор хорошо понимал, как нужно настраивать межсетевой экран, чтобы он смог эффективно работать в реальной среде. Существует очень тонкое равновесие между безопасностью, функциональностью и удобством эксплуатации. Если приложение чрезвычайно удобно для пользователя, оно, вероятнее всего, настолько же небезопасно. Чтобы сделать безопасное приложение действительно удобным для пользователя, разработчику, как правило, требуется выполнить большой объем дополнительной работы: предусмотреть возможные ошибки пользователей, создать дополнительные диалоговые окна, шаблоны, мастеры, написать пошаговые инструкции. В свою очередь, это может существенно «раздуть» код, что может стать причиной непредвиденных проблем. Эта «лишняя» работа и дополнительные проблемы не нужны производителям, поскольку обычно это не позволяет заработать дополнительные деньги, а имеет обратный эффект.
ПРИМЕЧАНИЕ. В последних версиях Windows многие сервисы по умолчанию отключены, пользователь должен специально включать их по мере необходимости. Это значительно ближе к реализации принципа «отсутствие доступа по умолчанию» (default with no access), но Microsoft еще есть, к чему стремиться.
Ошибки при внедрении и настройке программного обеспечения являются распространенной проблемой, которая становится причиной большинства нарушений безопасности в сетевой среде. Многие люди не осознают, что большое количество служб (многие из которые в действительности не нужны) включены по умолчанию сразу после установки системы. Эти службы могут позволить злоумышленникам получить важную информацию, которая поможет им при проведении атаки. А некоторые службы фактически открывают дверь в саму систему. Служба NetBIOS может быть использована для получения доступа к общим ресурсам в среде Windows, служба Telnet позволяет удаленному пользователю получить доступ к командной оболочке, другие службы также могут предоставлять доступ без ограничений. На многих системах работают сервисы FTP, SNMP, IRC (Internet Relay Chat), которые не обеспечивают никакой безопасности, тем более, что в действительности они зачастую не используются. Многие такие службы включаются по умолчанию и остаются включенными и доступными злоумышленникам, если администратор не позаботиться об их отключении или ограничении доступа к ним.

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

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

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


Многие обстоятельства непредсказуемы, поэтому очень трудно спланировать действия для реакции на них. Однако действия на случай подобных непредсказуемых ситуаций могут быть запланированы в общем виде, а не детально, для каждой ситуации в отдельности. Если в приложении возникает сбой по какой-либо причине, оно должно вернуться обратно в безопасное состояние. Для этого, например, может потребоваться перезагрузка операционной системы, после которой пользователь снова зарегистрируется в системе. Именно поэтому некоторые операционные системы в таких случаях отображают «синий экран» и / или автоматически перезагружаются. Когда в такой системе происходит что-то, что может перевести ее в неустойчивое или небезопасное состояние, система делает дамп содержимого оперативной памяти и выполняет полную перезагрузку.

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

Комментариев нет: