На главную | Содержание | Назад | Вперёд
Наши друзья

 

 

Шаблоны атак

Одна из серьезных проблем в области компьютерной безопасности заключается в отсутствии единой терминологии. Отдельные статьи в прессе отнюдь не помо­гают в этом деле. Негативное влияние оказывает некорректное использование тер­минов поставщиками программного обеспечения, которые стремятся убедить поку­пателя в необходимости покупки именно их программ. В этой главе мы определим значения нескольких терминов, которые будут использоваться в данной книге. Кто-то может не согласиться с нашими определениями и способами использования тер­минов. Достаточно сказать, что нашей целью является четкость и связность инфор­мации.
Первым и наиболее важным определением является цель атаки. Половина успе­ха атаки зависит от правильного выбора цели. Программа, которою локально или удаленно атакует хакер, называется атакуемым программным обеспечением (target software).
Целью атаки может быть сервер, подключенный в Internet, телефонный коммута­тор или изолированная система, которая управляет средствами противовоздушной обороны. До начала атаки следует определить уязвимые места выбранной цели. Иногда это называют оценкой риска (risk assesment). Если обнаруживается серьез­ное уязвимое место, то цель атаки отлично подходит для взлома.
После выполнения программы получается тот или иной результат. При тестиро­вании проверяются результаты выполнения программы, с тем чтобы определить, что ошибка приводит к отказу в работе программы. Чем больше данных предоставляет программа на выходе, тем легче определить ошибочные внутренние состояния в программе и т.д. Наблюдаемость — это вероятность того, что ошибка в программе будет выявлена по выходным данным. Чем выше наблюдаемость, тем проще протес­тировать конкретный фрагмент программного обеспечения. Невозможно выявить ошибочную ситуацию в программном обеспечении, которое не выдает никаких дан­ных. Хорошо наблюдаемой программой можно назвать ту, которая имеет встроен­ную возможность отладки выходных данных. Программа, которая имеет низкую на­блюдаемость, может быть изменена с помощью отладчика и улучшена до программы с высокой наблюдаемостью. Например, в случае, когда программа трассировки по­тока данных подключается к программе — цели атаки.


Технологии взлома программного обеспечения используют идеи наблюдаемости работы программ, особенно когда речь идет об удаленных атаках. В этой книге будет представлено множество методов по улучшению наблюдаемости. Основная идея за­ключается в сборе максимального объема информации о внутренних состояниях программы как статически, на этапе проектирования программы, так и динамически, при ее исполнении.
Классификация терминов
ДЛЯ определения риска в системе должны быть найдены уязвимые места. Серь­езная проблема в том, что уязвимые места в программном обеспечении в основном остаются неклассифицированными и неопределенными. Существует несколько на­учных трудов по этой тематике, но они слишком поверхностны и уже достаточно ус­тарели. Ободряет то, что за несколько последних лет многие программы атаки были выявлены и исследованы, а результаты этих исследований были опубликованы.
Основными источниками информации по уязвимым местам можно считать спи­сок рассылки bugtraq, в котором были впервые публично рассмотрены многие программы атаки (http://www.bugtraq.com), и базу данных уязвимых мест CVE (Common Vulnerabilities and Exposures — распространенные уязвимые места и ошибки), над формированием которой работают научные сотрудники. Обращаем внимание, что в начале нового века список рассылки bugtraq стал коммерческим проектом, который используется компанией Symantec для распространения своих баз данных (которые они предоставляют по подписке). База данных CVE представ­ляет собой еще одну попытку собрать все данные по уязвимым местам и ошибкам в одном месте. Недостатком CVE является отсутствие четкого разделения информа­ции по категориям. •
Два упомянутых нами форума позволяют убедиться, что ошибки в программном обеспечении широко распространены и повторяются в различных программных продуктах. Таким образом, существуют общие проблемы в программном обеспече­нии. Во многих аспектах ситуации переполнения буфера выглядят одинаково, неза­висимо от того, в какой конкретно программе они происходят.
Согласно нашей классификации, уязвимые места, ошибки (bug) и просчеты (flow) по своим базовым характеристикам объединены в единую категорию и фор­мируют единые шаблоны атак. Этот подход базируется на следующем предположе­нии. Подобные ошибки программирования приводят к однотипным методам про­ведения атак. Таким образом, постараемся осветить общие проблемы программного обеспечения, а не конкретные уязвимые места1. Благодаря общей системе классифи­кации можно использовать шаблон, согласно которому выполняется исследование крупных программных систем на предмет наличия уязвимых мест. Такой шаблон позволяет аудитору найти проблемные места в программах. Безусловно, такая ин­формация пригодится как для защиты систем, так и для проведения атак.


Ошибки
Ошибка (bug) — это погрешность в программном обеспечении. Заметим, что в программном обеспечении действительно могут содержаться ошибки и при этом ни­когда не исполняться. Хотя термин ошибка применяется достаточно широко многи­ми специалистами, мы его используем преимущественно для описания простых про­блем. Например, ошибкой является неправильное использование функции strep у () в программах на С и C+ + , что приводит к возможности переполнения буфера. Мы считаем, что ошибка представляет собой недостаток на уровне реализации, который можно без труда использовать в собственных целях. Ошибки могут присутствовать только в программном коде. Недостаток, допущенный на этапе проектирования, мы не будем называть ошибкой. Для выявления ошибок используются программы ска­нирования кода.
Просчеты
Просчет (flow) также является недостатком программного обеспечения, но про­блема здесь определяется на более глубоком уровне. Просчеты зачастую можно на­звать более тонкими и неприметными недостатками, чем простые очевидные ошиб­ки, например, просчет может проявляться в способе ссылки на массив или в исполь­зовании потенциально опасного системного вызова. Просчет обычно связывают как с программным кодом, так и со всем проектом. Например, несколько классических просчетов касаются механизма обработки ошибок и систем восстановления инфор­мации, и при возникновении ошибок в их работе создаются опасные ситуации. Еще одним примером просчета можно назвать атаки с использованием сценариев как следствие некорректного программирования. Заметим также, что вполне возможны ситуации, когда имеющиеся в программном обеспечении просчеты хакерами вовсе не используются.
Уязвимые места
Ошибки и просчеты образуют единый класс уязвимых мест (vulnerability) со­гласно специально разработанной классификации2. Уязвимое место — это недоста­ток программного обеспечения, которым может воспользоваться злоумышленник в своих корыстных целях.
Уязвимые места в программном обеспечении, связанные с системой безопасно­стью, варьируются от ошибок в локальной реализации (например, при использова­нии вызова функции gets () в программах на С и C++) и ошибок межпроцедурного взаимодействия (например ошибка, из-за которой становится возможной ситуация "гонки на выживание" во время между контрольной проверкой возможности досту­па и изменением файла) до недостатков более высокого уровня, допущенных на ста­дии проектирования (например, к ним относится некорректная обработка ошибок и систем восстановления, сбой которых приводит к небезопасным ситуациям, или
ошибок в системах совместного использования объектов, в которых ошибочно при­меняются транзитивные доверительные отношения)3.
Злоумышленникам нет никакого дела до того, является ли уязвимое место ре­зультатом серьезного просчета или простой ошибки, хотя ошибки проще использо­вать для атаки. Некоторые уязвимые места непосредственно позволяют провести полную атаку, а другие служат только начальным плацдармом для проведения более сложных атак.
Уязвимые места могут быть определены и по отношению к программному коду, в котором они присутствуют. Чем более сложным является уязвимое место, тем боль­ше кода придется проверить для его обнаружения. Иногда один только просмотр программного кода не дает никакого результата. Иногда же необходим более высо­кий уровень описания, нежели описание того, что именно исполняется в этом коде. Зачастую необходимо описание проекта. В других случаях требуется знать подроб­ности среды исполнения кода. Необходимо сказать, что есть существенное различие между обычными ошибками в программах и недостатками архитектуры программы. Для исправления простой ошибки часто достаточно одной строки кода, а просчет в архитектурном решении требует масштабных изменений, которые затрагивают мно­гие аспекты программы.
Например, обычно сразу можно сказать, что вызов функции gets () в програм­мах, написанных на языке С или C++, может быть успешно использован при прове­дении атаки на переполнение буфера, и для этого вовсе не нужно изучать остальную часть программного кода, весь проект или среду исполнения. Для использования ошибки переполнения буфера злоумышленник подает строку вредоносного теста на стандартный вход программы. Таким образом, уязвимое место, связанное с исполь­зованием функции gets (), может быть выявлено с высокой точностью при помощи элементарного лексического анализа.
Более сложные уязвимые места связаны со взаимодействием различных фраг­ментов программного кода. Например, точное определение состояния гонки на вы­живание требует изучения более чем одной строки программы. Для выявления по­добных уязвимых мест требуются знания об особенностях работы нескольких функ­ций, нужно иметь верное представление об учете использования глобальных переменных и быть максимально осведомленным об операционной системе, предос­тавляющей среду для выполнения этой программы.
Поскольку атаки становятся все более сложными, то и собственно определение того, что же является уязвимым местом определенного типа, постоянно изменяется. Атаки с использованием расчета по времени теперь уже стали повсеместными, тогда как всего несколько лет назад они считались "экзотическими". Аналогично, двух-этапные атаки на переполнение буфера с использованием "трамплинов" были рань­ше темой исследования научных работников, а теперь применяются в ежедневных атаках.
Уязвимые места на уровне проекта
Еще сложнее ситуация с уязвимыми местами, внесенными на уровне проекта. Для выявления ошибки на уровне проекта программы требуется огромный опыт. Поэтому очень сложно найти такие ошибки и еще сложнее автоматизировать про­цесс этого поиска. Проблемы на уровне проектирования наиболее распространены, однако им уделяется наименьшее внимание при оценке безопасности программного кода. Компания Microsoft сообщила, что около 50% ошибок, выявленных в ходе реа­лизации программы по проверке безопасности в 2002 году, составили именно ошиб­ки на уровне проектирования. Очевидно, что ошибкам этого типа должно уделяться больше внимания.
Рассмотрим обработку ошибок и систему восстановления. Восстановление после сбоя является важным аспектом создания систем по обеспечению безопасности. Но реализация восстановления довольно сложна, требует взаимодействия между моде­лями обработки ошибок, избыточности на стадии проектирования и защиты от атак отказа в обслуживании. Что касается объектно-ориентированной программы, то чтобы понять, безопасна ли обработка ошибок и система восстановления, необходи­мо оценить свойства, распределенные между несколькими классами, которые, в свою очередь, распределены в целом проекте. Код обнаружения ошибки обычно присут­ствует в каждом объекте и методе, а код обработки ошибки обычно создается от­дельно и не зависит от кода обнаружения. Иногда исключения передаются на сис­темный уровень и обрабатываются машиной, на которой запущена вызвавшая ис­ключение программа (например, обработка исключений виртуальной машиной Java 2). Это значительно усложняет задачу по определению того, является ли безопасным конкретный код обработки ошибок и проект восстановления после сбоя. К тому же эта проблема усугубляется в системах на основе транзакций, ши­роко используемых в решениях для электронной коммерции, в которых функцио­нальные возможности распределены между различными компонентами, запущен­ными на нескольких серверах.
К проблемам уровня проектов можно также отнести совместное использование объектов, некорректное наследование доверительных отношений, незащищенные каналы обмена данными (как внутренние, так и внешние), неправильные или отсут­ствующие механизмы контроля доступа, недостатки при аутентификации или входе в систему, ошибки гонки на выживание, связанные с вредоносным изменением дан­ных после выполненных проверок и до легитимного действия (особенно в многопо­точных системах) и многие другие. Более подробно о просчетах на уровне проектов программного обеспечения и о том, как избежать этих просчетов, рассказано в книге Building Secure Software.

 

На главную | Содержание | Назад | Вперёд
 
Яндекс.Метрика