|
| ||||||||||||
| ||||||||||||
|
2003 г
Безопасность систем с открытым кодомКриспин Кован07.08.2003 Открытые системы, #07-08/2003 Споры о том, приводит ли открытие кода к усилению или ослаблению безопасности программного обеспечения, длятся годами. Ни одно из этих утверждений нельзя считать абсолютной истиной: свободно распространяемое программное обеспечение открывает более широкие возможности и перед хакерами, и перед специалистами по безопасности. К счастью, существуют определенные технологии для систем с открытым кодом, которые могут помочь специалистам усилить защищенность своих решений.
Одни утверждают, что свободно распространяемые программы по своей природе более защищены, чем системы с недоступными исходными текстами [1], а другие считают, что это не так [2]. Ни одну из этих точек зрения нельзя назвать единственно правильной: по сути, это две стороны одной медали. Тем не менее, открытые коды дают специалисту по безопасности немалые преимущества, поскольку позволяют использовать методы, как правило, неприменимые к коммерческим программным продуктам. Если у пользователей нет доступа к исходным текстам, они вынуждены довольствоваться тем уровнем безопасности, который обеспечил производитель, в то время как открытые коды дают возможность пользователям добиться оптимального именно для них уровня. В данной статье описаны новые методы организации защиты, которые базируются на преимуществах программного обеспечения с открытым кодом. В первую очередь речь пойдет о программной безопасности (устранение уязвимых мест в программах), а не о сетевой (которая связана с протоколами и, таким образом, не зависит от того, доступны ли в открытых кодах другие сетевые компоненты). Все решения, упомянутые в статье, применимы только к системам с открытыми кодами, хотя сами они не всегда относятся к их числу. Безошибочного программного обеспечения для сложных систем не существует, так что придется искать иные средства, позволяющие убедиться, что крупные, сложные, вероятно уязвимые программы делают только то, что должны делать и ничего больше. Мы разделяем методы, которые гарантируют, что ПО «не делает ничего больше», на три большие категории.
Аудит программного обеспеченияНаименьший вред приносит то уязвимое место в программе, которое никогда не проявляется. Так что оптимально было бы иметь возможность предотвращать уязвимые места, проводя аудит программного обеспечения. Для этого идеально подходит открытый код. Недостаток такого подхода состоит в том, что аудит исходного текста, или даже поиск наиболее общих дефектов организации защиты в коде, — вещь очень сложная и требующая больших затрат времени. Отсюда следует, что гарантировать корректность данного фрагмента кода, крайне важного для обеспечения защиты, и найти для этого людей, достаточно компетентных для того, чтобы обнаружить уязвимые места, одинаково трудно. SardonixЦель проекта Sardonix состояла в решении социальных проблем, связанных с попытками убедить специалистов в необходимости проверять корректность кода и регистрировать свои результаты. В таблице 1 представлены некоторые статистические и динамические инструменты аудита программного обеспечения. Sardonix оценивает качество выполненного тестирования и самих программ в соответствии с собственной системой классификации. Система классификации аудиторов определяет качество проверки с учетом объема проанализированного кода и числа пропущенных ошибок (которые были обнаружены при последующей проверке корректности того же самого кода). Программы, в свою очередь, классифицируются по уровню своей надежности, в зависимости от того, кто именно проверял их. Эта система классификации дает программистам, претендующим на роль аудиторов, стимул для увеличения своего уровня в классификации Sardonix и возможность использовать этот показатель в своих резюме. Sardonix весьма полезен и для тестировщиков, не обладающих большим опытом. Он поддерживает центральное хранилище полезных ресурсов (в частности, описания и ссылки на инструменты аудита программного обеспечения, практические примеры, списки вопросов и ответов). Статические анализаторыСтатические анализаторы проверяют исходные тексты и сообщают о подозрительных строках кода, которые могут оказаться уязвимыми. В отличие от компиляторов «строго типизированных» языков, таких как Java и ML, статические анализаторы могут посчитать подозрительными совершенно безопасные фрагменты кода. Однако излишняя подозрительность приводит к увеличению соотношения ложных/истинных тревог. Если статический анализатор слишком часто поднимает тревогу, разработчики начинают относиться к нему с недоверием и зачастую вообще отказываются от него. Так что избирательность для анализатора исходных текстов абсолютно необходима. С другой стороны, анализатор должен обладать достаточно высокой восприимчивостью. Если анализатор пропускает некоторые случаи патологий, на поиск которых он рассчитан (нераспознавание ошибки), он внушает разработчикам ложное чувство уверенности. Таким образом, анализатор исходных текстов должен быть точным (т.е. восприимчивым и избирательным). К сожалению, в языках без строгого контроля типов, как правило, применяемых в разработке систем с открытым кодом (Си, Perl и т.д.), обнаружить дефекты защиты практически невозможно, и во многих случаях это требует слишком больших по сравнению с размером исходного текста ресурсов. Рассмотрим некоторые анализаторы исходных текстов, использующие разные эвристики, но при этом не способные дать абсолютно надежный результат. Такие инструментальные средства выступают лишь в качестве вспомогательного инструментария для специалиста, проверяющего корректность исходных текстов программ. Беркли. Ученые университета штата Калифорния в Беркли разработали несколько инструментальных средств статического анализа, способных обнаруживать определенные дефекты защиты.
RATS. Инструментарий Rough Auditing Tool for Security — утилита для проверки безопасности программ, написанных на языках Си, C++, Python, Perl и PHP. Сканирует исходный текст в поисках потенциально опасных вызовов функций. Цель разработки заключается не в том, чтобы непременно найти ошибки, — необходимо сделать обоснованные выводы, опираясь на которые специалист сможет вручную выполнять проверку кода. RATS использует сочетание проверок надежности защиты, от семантических проверок в ITS4 [7] до глубокого семантического анализа в поисках дефектов, способных привести к переполнению буфера, полученных из MOPS [3]. RATS распространяется в соответствии с лицензией GNU Public License (GPL). FlawFinder. Как и RATS, это статический сканер исходных текстов программ, написанных на Си и C++. Выполняет поиск функций, которые чаще всего используются некорректно, присваивает им коэффициенты риска (опираясь на такую информацию, как передаваемые параметры) и составляет список потенциально уязвимых мест, упорядочивая их по степени риска. FlawFinder распространяется бесплатно и с исходными текстами в соответствии с условиями GPL. Bunch. Средство анализа и визуализации программ, которое строит граф зависимостей, помогающий аудитору разобраться в модульной структуре программы. PScan. В июне 2000 года исследователи обнаружили новый и достаточно обширный класс уязвимых мест, получивший название «ошибки формата» [8]. Проблема связана с описателем формата %n оператора форматного вывода строк printf, который указывает число байт, выводимых для соответствующего аргумента printf, при условии, что данный аргумент существует и имеет тип int *. Этот описатель может быть использован для нарушения защиты, если программа позволяет передавать «неотфильтрованные» данные непосредственно как первый аргумент printf. Это действительно «дыра»: раньше повсеместно считалось, что строки формата совершенно безопасны. Впоследствии же в широко применяемых инструментальных средствах обнаружились десятки дефектов, связанных с форматами [9]. Теоретически причина «форматных» ошибок состоит в том, что соглашения о передаче аргументов в Си не проверяют корректность типов. В частности, механизм varargs позволяет функциям наподобие printf иметь различное число аргументов, «извлекая» из стека вызовов столько аргументов, сколько им необходимо, определяя на основе ранее извлеченных аргументов, сколько дополнительных аргументов и какого типа им еще нужно получить. PScan сканирует исходные тексты на Си в поисках потенциально некорректного использования функций, аналогичных printf, и выявляет уязвимые места в строках формата. И хотя область применения PScan довольно узка, это простой, быстрый и достаточно точный инструмент; однако он может пропускать функции, подобные printf, если они используются в определенных пользователями макросах. Динамические отладчикиПоскольку многие важные уязвимые места в защите невозможно обнаружить с помощью статического анализа, часто весьма полезным оказывается использование динамической отладки. Перечисленный ниже инструментарий генерирует необычные, но весьма важные тестовые случаи и оснащает программы средствами, позволяющими получить более детальный отчет об их деятельности. Sharefuzz. Fuzz (дословно «шпик») — термин, обозначающий проверку граничных условий программы за счет передачи входных значений, которые с большой вероятностью приведут к сбою (например, вызовут переполнение буфера и тем самым позволят обнаружить уязвимые места в строках формата printf). Идея заключается в том, чтобы передать входные значения, состоящие из необычно длинных строк или строк, содержащих %n, а затем проанализировать дамп ядра для этой программы. Sharefuzz автоматически выявляет переполнение в переменных среды в Unix-системах; может гарантировать, что все необходимые заплатки были установлены, и используются как средство обратного инжиниринга. ElectricFence. Отладчик операторов malloc() для Linux и Unix; останавливает работу программы именно на той команде, которая использует неполностью или приводит к выходу за границы буфера, зарезервированного с помощью malloc(). MemWatch. Инструментарий для выявления утечек памяти. Утечки происходят в тех случаях, когда программа с помощью malloc() резервирует некоторые данные, но никогда их не освобождает. Несогласующиеся операции malloc() и free() (когда одна и та же память несколько раз освобождается, память используется после того, как она освобождена, и так далее) могут привести к ошибкам с теми же последствиями, что и переполнение буфера. Предотвращение использования уязвимых местВсем описанным инструментам аудита для обработки даже весьма скромных по размеру программ требуется, по крайней мере, несколько часов. Такой подход становится неприемлемым, если программа содержит несколько миллионов строк кода. Еще один подход — предотвращение использования уязвимых мест — избавлен от проблем, связанных с длительностью обработки, точностью и определенностью. На его основе созданы инструменты (таблица 2), которые во время компиляции вставляют в программу датчики для обнаружения попыток использования во время работы программы дефектов ее защиты. Эти средства интегрируются в цепочку инструментария компиляции так, что программы могут компилироваться обычным образом и становятся защищенными. Время обработки, как правило, близко к нулю. (Некоторые инструменты предотвращают использование уязвимых мест, требуя, чтобы для увеличения точности анализа исходные тексты были снабжены специальными символами [5]. Однако эти средства обладают двумя недостатками — больше время обработки исходных текстов, что свойственно инструментарию аудита, и позднее время обнаружения, чем отличаются модули, предотвращающие использование уязвимых мест.) StackGuardStackGuard, по-видимому, был первым инструментарием предотвращения использования уязвимых мест [10]. Это дополнение к компилятору GCC (GNU Compiler Collection; gcc.gnu.org), который генерирует программы, устойчивые к такой разновидности переполнения буфера, как «разрушение стека» [11].
StackGuard выявляет дефект «разрушение стека» в процессе его возникновения за счет проверок целостности в записях активации вызовов функций, используя для этого метод проверки целостности canary («осведомитель») (рис. 1). Компилятор генерирует код, который вставляет специальный фрагмент в записи активации при вызовах функций, и проверяет их при возврате функций. Если происходит переполнение буфера типа «разрушение стека», специальный фрагмент будет искажен; код возврата при этом прекращает работу программы, а не передает управление на адрес, указываемый в искаженной записи активации. StackGuard широко применяется с лета 1998 года. Разработчики используют его для создания полных версий Immunix Linux на основе Red Hat 5.2, 6.2 и 7.0. Однако StackGuard 2 (текущая версия) базируется на GCC 2.91.66, а в период подготовки статьи был практически завершен перенос на GCC 3.2. Распространяется на условиях лицензии GPL. ProPoliceProPolice — программа, аналогичная StackGuard, но обладающая несколькими дополнительными возможностями.
StackGuard добавляет свои инструкции после этапа оптимизации, чтобы «осведомители» не были удалены или искажены. ProPolice помещает свои проверки на абстрактный уровень синтаксического дерева GCC, рискуя тем, что компилятор может помешать выполнению проверок, поместив их туда, где они будут неэффективными. FormatGuardFormatGuard аналогичен StackGuard: он выявляет и прекращает работу программы в случае использования уязвимых мест в строке формата printf [12]. FormatGuard был первым инструментарием, созданным для предотвращения использования уязвимых мест в строке формата оператора printf. В FormatGuard применяются макросы препроцессора CPP для подсчета аргументов времени компиляции и вокруг функций printf формируются оболочки времени исполнения, которые устанавливают соответствие между предполагаемым числом аргументов в строке формата и реально переданным числом аргументов. FormatGuard предлагается в виде вариата glibc на условиях LGPL. Управление поведениемУправление поведением реализует защиту, которая эффективна только во время исполнения. Обычно это осуществляется с помощью библиотек или ядра операционной системы. В таблице 3 дано краткое описание существующих инструментов управления поведением. Linux Security ModulesБлагодаря своей популярности и открытому коду, ОС Linux стала объектом большого числа исследований, посвященных совершенствованию модели контроля доступа. Однако наиболее перспективные системы защиты для большинства остаются недоступными. Их использование требует возможности компилировать и устанавливать настраиваемые ядра, что является серьезным препятствием для тех, кто по роду своей деятельности не связан с разработкой ядер Linux. Проект Linux Security Modules (LSM) [13] призван решить эту проблему за счет создания единого модульного интерфейса в ядре Linux, чтобы пользователи могли загружать усовершенствованные системы контроля доступа в стандартных ядрах Linux; после чего конечные пользователи могли бы адаптировать эти системы к своим требованиям. Для этого в рамках LSM необходимо добиться следующего.
В июне 2002 года Торвальдс согласился добавить LSM в Linux 2.5 (разрабатываемая сейчас версия ядра), так что вполне вероятно, что она станет стандартной возможностью в Linux 2.6. Контроль доступаПринцип минимальных привилегий [14] гласит: каждая операция должна выполняться с наименьшим набором привилегий, требуемых для данной операции. Данный принцип минимизирует риск проникновения в систему. К сожалению, строго следовать этому принципу невозможно, поскольку сами по себе средства контроля доступа становятся слишком сложными для управления. Необходимо найти компромисс между сложностью и выразительностью. Увы, стандартная схема прав доступа в Unix чересчур проста и зачастую недостаточно выразительна, чтобы определить минимально необходимые привилегии. Приведение типов и DTE. Реализует идею разделения пользователей по доменам, разделения файлов по типам и управление доступом, путем указания, какие домены к какому типу могут обращаться [15]. DTE (Domain and Type Enforcement) — усовершенствование этой концепции [16]. Серж Хеллин разрабатывает свободно распространяемую версию DTE, отражаемую на интерфейс LSM. Вопросы интеллектуальной собственности, возникающие в связи с приведением типов, чрезвычайно сложны. Механизм DTE защищен рядом патентов, но его реализации распространяются на условиях GPL. Пока не ясно, как эти вопросы будут разрешены. SELinux. Создан на основе приведения типов в компании Secure Computing. Также опирается на ядро Flask, разработанное в университете штата Юта и сейчас поддерживаемое NAI при финансировании Агентства национальной безопасности США. SELinux включает в себя широкий спектр функций для управления доступом и контроля безопасности, в том числе Role-Based Access Control [17]. SELinux играет определяющую роль в проекте LSM; распространяется исключительно как модуль LSM. SubDomain. Средство контроля доступа, упрощенного в расчете на серверные приставки [18]; гарантирует, что приставка будет делать то, для чего она предназначена и ничего кроме этого. Для этого служит механизм правил, определяющих, какие файлы каждой из программ откуда можно читать, куда записывать и где исполнять. В отличие от систем DTE и SELinux, в SubDomain выразительность была принесена в жертву простоте. SELinux позволяет формулировать более «хитроумные» правила, чем SubDomain, и служит для решения сложных задач контроля многопользовательского доступа. С другой стороны, SubDomain проще в управлении и быстрее подготавливается к работе. Так, сервер Immunix (в том числе SubDomain) удалось добавить в контекст Defcon Capture-the-Flag [19], в котором в течение 10 часов формировались профили SubDomain для самых разных и имеющих множество дефектов программ. Защита полученной системы ни разу не была нарушена. Существует реализация SubDomain в интерфейсе LSM. Linux Intrusion Detection System. Система, первоначально разработанная как модель доступа, призванная не допустить модификацию критически важных файлов с помощью любого процесса, если tty, управляющий этим процессом, не является физической консолью. Впоследствии LIDS архитектуру расширили, позволив работать с конкретными файлами строго определенным программам, аналогично тому, как это реализовано в SubDomain. Существует реализация LIDS в интерфейсе LSM. Блокираторы поведенияБлокираторы поведения предотвращают выполнение определенных операций, которые практически всегда связаны с программными атаками. Openwall. По существу, — заплатка для ядра Linux, усиливающая защиту ОС и включающая три блокиратора поведения.
Две последние возможности реализованы в интерфейсе LSM в виде модуля OWLSM. OWLSM, получивший свое название от аббревиатуры Openwall (OWL) и LSM, поддерживает правило «никаких ptrace для процессов суперпользователя», что защищает от ошибок при обработке ptrace в ядре Linux. Libsafe. Библиотека, созданная для стандартных функций glibc, проверяет корректность аргументов, предотвращая использование функций glibc для причинения вреда вызывающей программе [19]. Libsafe 2.0 может предотвращать использование дефектов, приводящих к переполнению буфера и некорректному использованию строки формата оператора printf, за счет прекращения выполнения функции, если она пытается переписать запись активации, которая вызывает функцию. Основное ограничение состоит в том, что данный механизм не действует, если программы скомпилированы с ключом fomit-frame-pointer (его часто применяют, чтобы предоставить компилятору GCC/x86 возможность зарезервировать еще один регистр). RaceGuard. Атаки с использованием временных файлов организуются в тех случаях, когда хакер пытается использовать промежуток времени при создании файла с помощью привилегированных программ (setuid). При обычных операциях создания временных файлов всегда есть промежуток времени между моментом, когда программа проверяет существование файла, и моментом, когда она записывает данные в этот файл [20]. RaceGuard защищает от такой формы атаки, максимально сокращая время между проверкой существования и доступом к файлу, тем самым не позволяя хакеру «проскользнуть» между операциями чтения и записи [21]. Эффективный доступ реализуется за счет использования так называемой «оптимистической блокировки» (optimistic locking): разрешаются обе операции доступа, но вторая операция записи блокируется, если она фантастическим образом указывает на другой файл, а не на тот, который был использован при первом обращении [22]. RaceGuard реализуют в интерфейсе LSM. Systrace. Гибридный инструментарий, объединяющий средства контроля доступа и блокиратор поведения для OpenBSD и NetBSD, как и SubDomain, позволяет системным администраторам указывать, к каким файлам может получить доступ каждая из программ. Кроме того, позволяет определять, какой системный вызов может выполнять программа, тем самым давая возможность реализовать определенный вид блокировки действий. Интегрированные системыРассмотрим три разработки, которые интегрируют некоторые из рассмотренных средств. OpenBSDИдея, лежащая в основе OpenBSD, состоит в том, чтобы использовать наилучшие практические решения для организации защиты. Все исходные тексты подвергаются тщательной проверке вручную. При установке по умолчанию разрешается лишь небольшое число сетевых служб, тем самым минимизируется потенциальная уязвимость системы, возникающая из-за случайных программных дефектов. OpenBSD также включает в себя вызов jail(), аналогичный широко распространенному механизму изоляции chroot(). Совсем недавно в OpenBSD была добавлена Systrace. Также в OpenBSD входит OpenSSH, свободно распространяемая версия популярного протокола SSH. Разработчики OpenBSD модернизировали OpenSSH, чтобы он мог использовать «разделение привилегий», что позволяет свести к минимуму уязвимость системы из-за ошибок в демоне SSH. Распространяется в открытых кодах. Openwall LinuxПо своей идеологии напоминает OpenBSD (контроль корректности исходных текстов и минимальные усилия по установке и конфигурированию), но ориентирован на Linux, а не на BSD. Использует блокираторы поведения Openwall. ImmunixЧтобы оставаться адекватным самым последним версиям программ, Immunix не применяет никаких средств аудита исходных текстов. Вместо этого он компилирует эти тексты вместе со средствами предотвращения использования уязвимых мест (Stack-Guard и FormatGuard), тем самым не давая хакерам возможность проникнуть в систему через большинство уязвимых мест. Хотя многие компоненты Immunix распространяются в открытых кодах, система целиком является коммерческой. EnGardeEnGarde — коммерческий вариант Linux, дополненный элементами контроля доступа LIDS. Открытые вопросыВсе рассмотренные инструменты разработаны для или на основе систем с открытым кодом. К коммерческим же системам они применимы в разной степени, поскольку требуют либо доступа к исходным текстам приложения, либо модификации ядра или библиотек операционной системы. Средства предотвращения использования уязвимых местMicrosoft предложила возможность StackGuard для компилятора Visual C++ 7.0 [23]. В принципе, это имеет то же значение для укрепления защиты, что и свободно распространяемые системы, но на практике воспользоваться этим механизмом могут только распространители кода, поскольку никто другой не имеет исходных текстов, которые можно использовать для компиляции. Средства управления действиямиРяд производителей предлагает коммерческие инструменты защиты, рекламируя свои продукты как средства, «предотвращающие проникновение на узлы сети». Среди них — компания Entercept (блокиратор поведения, который предотвращает использование ряда известных уязвимых мест) и Okena (система контроля доступа на основе профилей, аналогичная Systrace). В данном случае преимущества систем с открытым кодом проявляются довольно слабо: возможность чтения исходных текстов приложения может в чем-то помочь при создании профиля для приложения, но определяющего значения не имеет. Главное преимущество открытых исходных текстов заключается в том, что исследователи и разработчики могут достаточно просто добавить такого рода возможности к операционным системам с открытым кодом. Программное обеспечение с открытым кодом усиливает угрозу безопасности системы, но одновременно и дает определенное преимущество при ее организации. Угроза заключается в том, что наличие исходного текста помогает хакерам быстрее создавать новые эксплоиты. Преимущество же состоит в том, что наличие исходного текста дает возможность сколь угодно высоко поднимать уровень безопасности систем, независимо от предпочтений производителя. Тот факт, что программы с открытым кодом позволяют увеличивать уровень безопасности системы, имеет поистине революционное значение, и его высоко оценят организации, которым требуется надежная защита. Больше нет необходимости довольствоваться тем, что навязывает производитель. Пользователи могут применять для укрепления защиты своих систем самые передовые технологии или выбрать поставщика инструментария с открытым кодом, который объединяет одну или несколько подобных технологий, чтобы создать более защищенные системы, сохранив при этом совместимость с их немодернизированными аналогами. Литература
Криспин Кован (crispin@wirex.com) — директор по науке компании WireX Communications. Специализируется на создании решений, позволяющих усилить защиту информационных систем. Crispin Cowan, Software Security of Open-Source Systems. IEEE Security & Privacy, January-February 2003. IEEE Computer Society, 2003, All rights reserved. Reprinted with permission. |
|
CITForum © 1997–2025