Теория операционных систем

         

Безопасность

 

Justi cause you're paranoid
Don't mean they aren't after you.
K. Kobain

To, что ты параноик
He значит, что они тебя не преследуют.
К. Кобэйн

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


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

Формулировка задачи

  А мальчик-юзер пошел пить пиво со злыми интернетчиками, а те ему и говорят: "Да какой-ты крутой хаксор. Почту ты сломал, факт. А вот этот сервак попробуй сломать". И в окно показывают. А напротив пивняка стоит здание, с надписью "Почта". И мальчик-юзер пошел почту ломать. А па почте, видать, сниффер стоял, так что через пять минут менты-модераторы приехали и так отмодерили мальчика-юзера, что с тех пор о нем ничего неизвестно.
Vitar Velazquez

Идеальная система безопасности должна обеспечивать полностью прозрачный санкционированный доступ к данным и непреодолимые трудности при попытках доступа несанкционированного. Кроме того, она должна предоставлять легкую и гибкую систему управления санкциями; во многих случаях бывает также полезно отслеживать все попытки несанкционированного доступа.
К сожалению, несмотря на огромную практическую важность, единой и связной теории безопасности вычислительных систем на сей день не разработано. Отчасти это объясняется сложностью и многосторонностью задачи: несанкционированный доступ к данным, например, может быть получен не только путем удаленного "взлома" вычислительной системы, но и посредством физического похищения компьютера или носителей данных, или с помощью подкупа сотрудника организации, имеющего доступ к данным. Следовательно, идеальная система безопасности должна предусматривать средства защиты от всех физически реализуемых способов несанкционированного доступа.
Понимаемая таким образом идеальная система безопасности, по-видимому, физически не решшзуема. В лучшем случае удается исключить отдельные способы, но для идеального решения задачи это нужно сделать по отношению ко всем способам получения несанкционированного доступа. На практике обычно исходят из требований "разумной достаточности" или экономической целесообразности: с одной стороны, стоимость установки и эксплуатации систем безопасности не должна превосходить ценности защищаемых данных. С другой, "экономически идеальная" система безопасности должна быть достаточно сложной, для того чтобы выгоды потенциального взломщика от получения доступа были ниже затрат на преодоление защиты.
Практическое применение этого критерия требует оценки стоимостей и их сравнения. Использование как показателя цен сопряжено с серьезной методологической сложностью, которую вкратце можно описать следующим образом: рыночная цена любого предмета — это цена, по которой обладатели такого предмета, желающие его продать, реально могут его продать, а желающие купить — соответственно, могут купить. В нашем же случае, обладатель защищаемого объекта часто вовсе не намерен его продавать, а те, от кого он защищается, не планируют его покупать. Даже если полный эквивалент защищаемого объекта может быть куплен, требуемая для этого сумма является лишь нулевым приближением для оценки реального ущерба пострадавшего или прибыли взломщика.
И в том случае, когда охраняемый объект — это деньги (например, база данных со счетами клиентов банка), потери от его похищения или нарушения целостности часто значительно превосходят непосредственно потерянную при этом сумму денег. Так, банк, пострадавший от взлома системы управления счетами, теряет не только переведенную на счет взломщика сумму, но и доверие клиентов.
Многие из объектов, с которыми вынуждены иметь дело разработчики систем безопасности, вообще не могут быть куплены. Все примеры конфиденциальных данных, перечисленных в начале этой главы, относятся именно к этой категории. Если охраняемый объект в принципе не покупается и не продается, то его цена попросту не определена (что, впрочем, не означает, что такой объект заведомо нельзя оценить).
Критерием принятия решения в такой ситуации могут быть лишь: субъективное решение владельца охраняемого объекта, сравнивающего стоимости объекта и стоимости охранных систем или те или иные представления о субъективной системе ценностей самого взломщика, оценивающего возможные прибыли и издержки.
Формулируя такие представления, разработчик архитектуры безопасности вынужден принимать во внимание также и людей, для которых вскрытие чужих систем безопасности является самоцелью, своего рода спортом. Обсуждение вопроса о том, можно ли охарактеризовать систему ценностей таких людей как извращенную, уведет нас далеко от темы книги. Для целей дальнейшего обсуждения важно отметить, что классификация этих людей как извращенцев и даже заочная постановка им того или иного мозговедческого диагноза никак не может защитить нас от них самих и результатов их деятельности.
Таким образом, заказчик системы безопасности вынужден принимать решение, в основе которого лежат не поддающиеся строгому обоснованию и, возможно, неверные представления о системах ценностей других людей. Задача, стоящая перед ним, находится в близком родстве с задачей, которую решает предприниматель, пытающийся оценить рыночные перспективы того или иного товара. Как и предприниматель, заказчик системы безопасности в случае принятия неверного решения рискует понести серьезные материальные потери, поэтому принятие решения о структуре и стоимости
системы безопасности вполне можно считать разновидностью предпринимательского решения.
Принятие предпринимательских решений в общем случае является неформализуемой и неалгоритмизуемой задачей. Во всяком случае, для ее формализации и алгоритмизации необходимо, ни много ни мало, создать ПОЛНУЮ универсальную формальную алгоритмическую модель человеческой психики, которая полностью описала бы поведение не только предпринимателя но и всех его потенциатьных деловых партнеров (а в случае системы безопасности — и всех потенциальных взломщиков этой системы). Даже если эта задача в принципе и разрешима, то, во всяком случае, она находится далеко за пределами возможностей современной науки и современных вычислительных систем. Возможно, этот факт и является фундаментальной причиной, по которой теория систем безопасности представляет собой логически несвязное сочетание эмпирических, теоретических или "интуитивно очевидных" рекомендаций разного уровня обоснованности.
Несмотря на все методологические и практические сложности, с которыми сопряжено применение экономической оценки к системам безопасности, по крайней мере, некоторые практически важные рекомендации этот подход нам может дать.
Во-первых, мы можем утверждать, что хорошая система безопасности должна быть сбалансированной, причем прежде всего с точки зрения взломщика: стоимости всех мыслимых путей получения доступа к системе должны быть сопоставимы. И, наоборот, должны быть сопоставимы стоимости мероприятий по обеспечению защиты от проникновения разными способами. Бессмысленно ставить бронированные ворота в сочетании с деревянным забором.
Это соображение, впрочем, ни в коем случае не должно удерживать нас от применения \;ор, которые при небольшой стоимости необычайно затрудняют несанкционированный доступ. Принцип сбалансированности необходимо применять в первую очередь к дорогостоящим, но при этом умеренно эффективным мероприятиям.
Вторая полезная рекомендация — это совет: если это оправданно по стоимостным показаниям, делать системы безопасности многослойными или, используя военную терминологию, эшелонированными. Пройдя внешний слой защиты (например, преодолев брандмауэр и установив прямое соединение с одним из серверов приватной сети компании), взломщик должен получать доступ не непосредственно к данным, а лишь к следующему слою защиты (например, средствам аутентификации ОС или серверного приложения).
Третья рекомендация в известной мере противоречит двум предыдущим и гласит, что учитывая компоненты стоимости эксплуатации системы безопасности, нельзя забывать о тех действиях, которые эта система требует от сотрудников организации. Если требования безопасности чрезмерно обременительны для них, то они могут попытаться осуществить операцию, которую в неоклассической экономике называют экстернализацией издержек (например, выдвинуть ультимативное требование — либо вы снимаете наиболее раздражающие из требований, либо повышаете зарплату, либо мы все уволимся).
Более неприятная для разработчика системы безопасности перспектива — это отказ (не всегда сознательный) от выполнения требований, создающий неконтролируемые дыры в системе безопасности. Например, ключи могут оставляться под половиком, пароли — записываться на прилепленных к монитору бумажках, конфиденциальные данные — копироваться на недостаточно защищенные настольные или переносные компьютеры и т. д.
В дальнейшем в этой главе мы будем обсуждать то подмножество задачи обеспечения безопасности, с которым практически сталкиваются разработчики программного обеспечения и системные администраторы. А именно, в большинстве случаев мы будем предполагать, что помещение, где размещена вычислительная система, защищено от несанкционированного проникновения, а персоналу, который имеет прямой или удаленный доступ к системе, в определенной мере можно доверять. Причина, по которой мы принимаем эти предположения, совершенно прозаична: в большинстве современных организаций за обеспечение такой безопасности отвечает не системный администратор, а совсем другие люди. На практике, хотя системный администратор и не обязан быть по совместительству специалистом в вопросах охраны и подбора персонала, но должен так или иначе взаимодействовать с этими людьми, вырабатывая согласованную и сбалансированную политику защиты организации.
Не следует думать, что эти допущения позволят решить перечисленные задачи идеально или, тем более, что они могут быть решены идеально. Не означают эти предположения также и того, что без разрешения этих задач системный администратор вообще не может приступать к работе — более того, мы рассмотрим и некоторые подходы к решению нашей задачи в ситуации, когда эти предположения выполняются лишь частично или не выполняются совсем. Большинство таких подходов основаны на шифровании и электронной подписи данных.
Даже в такой ограниченной формулировке задача обеспечения безопасности вовсе не проста и требует дополнительной декомпозиции. Задачу управления доступом к данным и операциям над ними разбивают на две основные подзадачи: аутентификацию (проверку, что пользователь системы действительно является тем, за кого себя выдает) и авторизацию (проверку, имеет ли тот, за кого себя выдает пользователь, право выполнять данную операцию).

Сессии и идентификаторы пользователя

Как правило, далеко не каждая авторизация отдельных операций сопровождается актом аутентификации. Чаше всего используется принцип сессий работы с вычислительной системой. В начале работы пользователь устанавливает соединение и "входит" в систему. При "входе" происходит его аутентификация.
Для того чтобы быть аутентифицированным, пользователь должен иметь учетную запись (account) в системной базе данных. Затем пользователь проводит сеанс работы с системой, а по завершении этого сеанса аннулирует регистрацию.
Одним из атрибутов сессии является идентификатор пользователя (user id) или контекст доступа (security context), который и используется при последующих авторизациях. Обычно такой идентификатор имеет две формы: числовой код, применяемый внутри системы, и мнемоническое символьное имя, используемое при общении с пользователем.

Сессии в Unix
Например, в системах семейства Unix пользователь идентифицируется целочисленным значением uid (user identifier). С каждой задачей (процессом) связано два идентификатора пользователя: реальный и эффективный. В большинстве случаев эти идентификаторы совпадают (ситуации, когда они не совпадают, подробно обсуждаются в разд.

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

  Петли дверные
Многим скрипят, многим поют:
"Кто вы такие,
Вас здесь не ждут!"
В. Высоцкий

Понятно, что если права доступа выделяются на основе машинного идентификатора пользователя, то возникает отдельная проблема установления соответствия между этим машинным идентификатором и реальным человеком. Такое соответствие не обязано быть взаимно однозначным: один человек может иметь несколько идентификаторов или наоборот, несколько человек могут пользоваться одним идентификатором. Тем не менее, способ установления такого соответствия необходим.
По-английски процесс входа в систему называется login (log in) и происходит от слова log, которое обозначает регистрационный журнал или процесс записи в такой журнал. В обычном английском языке такого слова нет, но в компьютерной лексике слова login и logout прижились очень прочно.
Наиболее точным переводом слова login является регистрация. Соответственно, процесс выхода называется logout. Его точная русскоязычная калька — разрегистрация — к сожалению, очень неблагозвучна.
Теоретически можно придумать много разных способов идентификации, например, с использованием механических или электронных ключей или даже тех или иных биологических параметров, например, рисунка глазного дна. Однако подобные способы требуют специальной и зачастую довольно дорогой аппаратуры. Наиболее широкое распространение получил более простой метод, основанный на символьных паролях.
Пароль представляет собой последовательность символов. Предполагается, что пользователь запоминает ее и никому не сообщает. Этот метод хорош тем, что для его применения не нужно никакого дополнительного оборудования — только клавиатура, которая может использоваться и для других целей. Но этот метод имеет и ряд недостатков.
Использование паролей основано на следующих трех предположениях:

пользователь может запомнить пароль; никто не сможет догадаться, какой пароль был выбран; пользователь никому не сообщит свой пароль.

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

Словарная атака в исполнении червя Морриса
Возможности словарной атаки впервые были продемонстрированы в 1987 году молодым тогда студентом Робертом Моррисом [КомпьютерПресс 1991]. Разработанная им программа — "червь Морриса" — использовала словарную атаку и последующий вход в систему с подобранным паролем как один из основных способов размножения. Червь использовал для распространения и другие приемы, продемонстрировавшие не только специфические изъяны тогдашних ОС семейства Unix, но и несколько фундаментальных проблем компьютерной безопасности, поэтому мы еще несколько раз будем возвращаться к обсуждению этой программы.

Червь Морриса использовал при подборе паролей следующие варианты:

входное имя пользователя; входное имя с символами в обратном порядке — "задом наперед"; компоненты полного имени пользователя — имя (first name), фамилию (last name) и другие элементы, если они есть; те же компоненты, но задом наперед; слова из заранее определенной таблицы, содержащей 400 элементов.

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

С первого взгляда видно, что таких "легко запоминаемых" вариантов довольно много — никак не меньше нескольких сотен. Набор их вручную занял бы очень много времени, но для компьютера несколько сотен вариантов — это доли секунды. Первый слой защиты от подбора пароля заключается именно в том, чтобы увеличить время подбора. Обнаружив неправильный пароль, наученные горьким опытом современные системы делают паузу, прежде чем позволят повторную попытку входа с того же терминального устройства. Такая пауза может длиться всего одну секунду, но даже этого достаточно, чтобы увеличить время подбора пароля от долей секунды до десятков минут.
Второй слой зашиты заключается в том, чтобы усложнить пароль и тем самым увеличить количество вариантов. Даже очень простые усложнения сильно увеличивают перебор. Так, простое требование использовать в пароле буквы и верхнего, и нижнего регистров увеличивает перебор в 2n раз где n — длина пароля. В большинстве современных систем пароль обязан иметь длину не менее шести символов, т. е. количество вариантов увеличивается в 64 раза. Требование использовать в пароле хотя бы один символ, не являющийся буквой, увеличивает число вариантов в 6x43 = 258 раз (в наборе ASCII 43 небуквенных графических символа). Вместо десятков минут подбор пароля, который содержит буквы разных регистров и хотя бы один спецсимвол, займет много дней.
Но если взломщику действительно нужно попасть в систему, он может подождать и несколько дней, поэтому необходим третий слой защиты — ограничение числа попыток. Все современные системы позволяют задать число неудачно набранных паролей, после которого имя блокируется. Это число всегда больше единицы, потому что пользователь — это человек, а людям свойственно ошибаться, но в большинстве случаев такой предел задается не очень большим — обычно 5—7 попыток. Однако, этот метод имеет и оборотную сторону — его можно использовать для блокировки пользователей.
Интересный вариант того же метода заключается в увеличении паузы между последовательными неудачными попытками хотя бы в арифметической прогрессии.
Наконец, последний слой защиты — это оповещение пользователя (а иногда и администратора системы) о неудачных попытках входа. Если пользователь сам только что нажал не ту кнопку, он при входе увидит, что была одна неудачная попытка, и не будет волноваться; однако, если есть сообщения о дополнительных неудачных попытках, время побеспокоиться и разобраться, что же происходит.
Современная техника выбора паролей обеспечивает достаточно высокую для большинства практических целей безопасность. В тех случаях, когда эта безопасность представляется недостаточной — например, если следует всерьез рассматривать опасность принуждения пользователя к раскрытию пароля — можно применять альтернативные методы идентификации, перечисленные ранее, т. е. основанные на механических или электронных ключах или биометрических параметрах. Впрочем, как уже говорилось, такие методы требуют применения специальной аппаратуры.
При использовании паролей возникает отдельная проблема безопасного хранения базы данных со значениями паролей. Как правило, даже администратор системы не может непосредственно получить значения паролей пользователей. Можно привести несколько соображений в пользу такого ограничения.

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

Для обеспечения секретности паролей обычно используют одностороннее шифрование, или хэширование, при котором по зашифрованному значению нельзя восстановить исходное слово. При этом программа аутентификации кодирует введенный пароль и сравнивает полученное значение (хэш) с хранящимся в базе данных. Существует много алгоритмов хэширования, при использовании которых узнать реальное значение пароля можно только путем полного перебора всех возможных вариантов и сравнения зашифрованной строки со значением в базе данных.
В старых системах семейства Unix пароль использовался в качестве ключа шифрования фиксированной строки алгоритмом DES (см. главу 1). Этот алгоритм ограничивает длину ключа 64 битами, соответственно пароли в таких системах могут содержать не более 8 символов. Современные системы используют алгоритм MD5 [RFC 1321], который допускает пароли практически неограниченной длины. Этот алгоритм специально разрабатывался с целью максимального усложнения задачи построения сообщения с заданным значением хэша.
Отцам-основателям Unix такой механизм обеспечения секретности показался настолько надежным, что они даже не стали ограничивать доступ обычных пользователей к хэшам чужих паролей, и выделили для их хранения поле в общедоступном для чтения файле /etc/passwd.
Однако "червь Морриса" продемонстрировал, что для подбора паролей не нужно перебирать все возможные комбинации символов, поскольку пользователи склонны выбирать лишь ограниченное подмножество из них. Процесс, имеющий возможность непосредственно читать закодированные значения паролей, может осуществлять подбор, не обращаясь к системным механизмам аутентификации, т. е. делать это очень быстро и практически незаметно для администратора.
После осознания опасности словарных атак разработчики систем семейства Unix перенесли значения паролей в недоступный для чтения файл /etc/shadow, где пароли также хранятся в односторонне зашифрованном виде. Это значительно усложняет реализацию словарной атаки, поскольку перед тем, как начать атаку, взломщик должен получить доступ к системе с привилегиями администратора. В наше время все способы получения не санкционированного доступа к парольной базе данных считаются "дырами" в системе безопасности.
Практически все современные системы хранят данные о паролях в односторонне зашифрованном виде в файле, недоступном для чтения обычным пользователям. Поставщики некоторых систем, например Windows NT/2000/XP, даже отказываются публиковать информацию о формате этой базы данных, хотя это само по себе вряд ли способно помешать квалифицированному взломщику.

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

Когда пользователь работает с консоли компьютера или с терминала, физически прикрепленного к терминальному порту, модель сессий является вполне приемлемой. При регистрации пользователя создается сессия, ассоциированная с данным терминалом, и далее проблем нет. Аналогично нет никаких проблем при подключении через сеть с коммутацией каналов, например, при "дозвоне" через модем, подключенный к телефонной сети (конечно же, при условии, что мы доверяем связистам). Когда соединение разрывается, сессия считается оконченной.
В сетях с коммутацией пакетов, к которым относится большинство современных сетевых протоколов (TCP/IP, IPX/SPX, ISO/OSI и т. д.), вообще нет физического понятия соединения. В лучшем случае сетевой протокол предоставляет возможность создавать виртуальные соединения с "надежной" связью, в которых гарантируется отсутствие потерь пакетов и сохраняется порядок их поступления. С таким виртуальным соединением вполне можно ассоциировать сессию, как это сделано в протоколах telnet, rlogin/rsh и ftp.

Протокол telnet
Протокол telnet используется для эмуляции алфавитно-цифрового терминала через сеть. Пользователь устанавливает соединение и регистрируется в удаленной системе таким же образом, как он регистрировался бы с физически подключенного терминала. Например, в системах семейства Unix создается виртуальное устройство, псевдотерминал (pseudotermina/) /dev/ptyXX, полностью эмулирующее работу физического терминала, и система запускает ту же программу идентификации пользователя /bin/login, которая используется для физических терминалов. При окончании сессии соединение разрывается и псевдотерминальное устройство освобождается.

Виртуальные сессии вынуждены полагаться на то, что сетевой протокол обеспечивает действительно гарантированное соединение, т. е. что никакая посторонняя машина не может вклиниться в соединение и прослушать его идИ послать свои поддельные пакеты. Обеспечение безопасности на этом уровне либо требует доверия к сетевой инфраструктуре физического, канального и сетевого уровней (линиям связи, коммутаторам и маршрутизаторам), либо сводится к использованию шифрования и/или криптографической подписи пакетов.
В протоколах, использующих датаграммные соединения, средствами протокола виртуальную сессию создать невозможно. Обычно в этом случае каждый пакет содержит идентификатор пользователя или сессии, от имени которого (в рамках которой) этот пакет послан. Такой подход применяется в протоколах работы с файловыми серверами NFS и NCP (Netware Core Protocol, используемый файловыми серверами Novell Netware). Датаграммные протоколы оказываются несколько более уязвимы для подделки пакетов и прочих вредоносных воздействий.

Подпись пакетов в NCP
Например, NCP, работающий через датаграммный протокол IPX, реализует свой собственный механизм поддержки сессий: все пакеты данной сессии имеют 8-битный номер, и пакеты с неправильными номерами просто игнорируются. Одна из техник взлома Netware 3.11 (так называемая "Голландская атака") состоит в посылке в течение короткого времени 256 пакетов с различными номерами — хотя бы один пакет окажется удачным. Для борьбы с такими действиями в Netware 3.12 была введена криптографическая подпись пакетов в пределах сессии.

Проблема дополнительно усложняется тем обстоятельством, что в сети зачастую взаимодействие происходит между системами, каждая из которых позволяет одновременную работу нескольких пользователей. Часто возникает желание требовать от пользователя регистрации только в одной из систем, а доступ в остальные системы предоставлять автоматически.
Обычно для автоматической регистрации используется модель доверяемых систем (trusted hosts). Если система В доверяет системе А, то все пользователи, зарегистрированные на системе А, автоматически получают доступ к системе В под теми же именами (рис. 12.2). Иногда аналогичную возможность можно предоставлять каждому пользователю отдельно — он сообщает, что при регистрации входа из системы А пароля запрашивать не надо. Разновидностью модели доверяемых систем можно считать единую базу учетных записей, разделяемую между машинами.

Рис. 12.2. Доверяемые системы

Межмашинное доверие в rlogin/rsh
Протоколы rlogin/rsh, обеспечивающие запуск отдельных команд или командного процессора на удаленной системе, используют файл /etc/hosts.equiv или .rhosts в домашнем каталоге пользователя на удаленной системе. Файл /etc/hosts.equiv содержит имена всех машин, которым наша система полностью доверяет. Файл .rhosts состоит из строк формата
имя.удаленной.машины имя пользователя
При этом имя.удаленной.машины не может быть произвольным, оно обязано содержаться в файле /etc/hosts, в котором собраны имена и адреса всех удаленных машин, "известных" системе. То же требование обязательно и для машин, перечисленных в /etc/hosts.equiv.
Например, пользователь fat на машине iceman.cnit.nsu.ru набирает команду
rlogin -I fat Indy.cnit.nsu.ru
— войти в систему lndy.cnit.nsu.ru под именем fat. Если домашний каталог пользователя fat на целевой машине содержит файл .rhosts, в котором есть строка iceman.cnit.nsu.ru fat, то пользователь fat получит доступ к системе Indy без набора пароля. Того же эффекта можно добиться для всех одноименных пользователей, если /etc/hosts.equiv содержит строку ice man.cnit.nsu.ru
Если же fat наберет команду
rlogin -1 root Indy.cnit.nsu.ru,
а в домашнем каталоге пользователя root файла .rhosts нет или он не содержит вышеприведенной строки, команда rlogin потребует ввода пароля, независимо от содержимого файла /etc/hosts.equiv. Нужно отметить, что администраторы обычно вообще не разрешают использовать rlogin для входа под именем root, потому что этот пользователь является администратором системы и обладает очень большими привилегиями.

Модель доверяемых систем обеспечивает большое удобство для пользователей и администраторов и в различных формах предоставляется многими сетевыми ОС. Например, в протоколе разделения файлов SMB. применяемом в системах семейства СР/М, Linux и др., используется своеобразная модель аутентификации, которую можно рассматривать как специфический случай доверяемых систем.

Аутентификация SMB
Аутентификация в SMB основана на понятии домена (domain). Каждый разделяемый ресурс (каталог, принтер и т. д.) принадлежит к определенному домену, хотя и может быть защищен собственным паролем. При доступе к каждому новому ресурсу необходимо подтвердить имя пользователя и пароль, после чего создается сессия, связанная с этим ресурсом. Для создания сессии используется надежное соединение, предоставляемое транспортным протоколом, — именованная труба NetBEUI или сокет TCP. Ввод пароля при каждом доступе неудобен для пользователя, поэтому большинство клиентов— просто запоминают пароль, введенный при регистрации в домене, и при подключении к ресурсу первым делом пробуют его. Благодаря этому удается создать у пользователя иллюзию однократной регистрации. Кроме того, если сессия по каким-то причинам оказалась разорвана, например из-за перезагрузки сервера, то можно реализовать прозрачное для пользователя восстановление этой сессии.
С точки зрения клиента нет смысла говорить о межмашинном доверии — клиенту в среде SMB никто не доверяет и вполне справедливо: обычно это система класса ДОС, не заслуживающая доверия. Однако серверы обычно передоверяют проверку пароля и идентификацию пользователя выделенной машине, называемой контроллером домена (domain controller). Домен обязан иметь один основной (primary) контроллер и может иметь несколько резервных (backup), каждый из которых хранит реплики (периодически синхронизуемые копии) базы учетных записей. При поступлении запроса на соединение сервер получает у клиента имя пользователя и пароль, но вместо сверки с собственной базой данных он пересылает их контроллеру домена и принимает решение о принятии или отказе в аутентификации на основании вердикта, вынесенного контроллером.
Только контроллеры домена хранят у себя базу данных о пользователях и паролях. При этом основной контроллер хранит основную копию базы, а резервные серверы — ее дубликаты, используемые лишь в тех случаях, когда основной сервер выключен или потерян. Благодаря тому, что все данные собраны в одном месте, можно централизованно управлять доступом ко многим серверам, поэтому домены представляют неоценимые преимущества при организации больших многосерверных сетей.

С точки зрения безопасности доверяемые системы имеют два серьезных недостатка.

1. Прорыв безопасности на одной из систем означает, по существу, прорыв на всех системах, которые доверяют первой (рис. 12.3). 2. Возникает дополнительный тип атаки на систему безопасности: машина, которая выдает себя за доверяемую, но не является таковой (рис. 12.4).

Рис. 12.3. Прорыв безопасности в сети с доверяемыми системами

12.4. Имитация доверяемой системы

Первая проблема является практически неизбежной платой за разрешение автоматической регистрации. Наиболее ярко эта проблема была проиллюстрирована упомянутым выше "Червем Морриса" (КомпьютерПресс 1991], который, проникнув в одну из систем, использовал содержимое файлов .rhosts и /etc/hosts.equiv для проникновения в доверяющие системы, полагаясь на то, что межсистемное доверие обычно делают взаимным. Поэтому в средах с высокими требованиями к безопасности часто стремятся ограничить число доверяемых систем, подобно тому, как отсеки кораблей разделяют водонепроницаемыми переборками.
Вторая проблема может быть отчасти решена использованием средств, пре-достаапяемых сетевыми протоколами, например, привязкой всех логических имен доверяемых систем к их сетевым адресам канального уровня. В протоколах TCP/IP это может быть сделано с использованием протокола аrр (Address Resolution Protocol — протокол разрешения адресов), однако надежда на это слаба: многие сетевые карты имеют настраиваемые адреса, а многие реализации сетевых протоколов допускают отправку пакетов с поддельным адресом отправителя.
Более изощренный и намного более надежный метод основан на использовании алгоритма двухключевого шифрования RSA или родственных ему механизмов.


Криптографические методы аутентификации

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

Система А генерирует последовательность байтов, обычно случайную, кодирует ее своим ключом и посылает системе В. Система В раскодирует ее своим ключом. Это возможно, только если системы владеют парными ключами. Системы тем или иным способом обмениваются "правильными" значениями зашифрованной посылки.

Аутентификация SSH
Для примера рассмотрим принцип RSA-аутентификации в пакете ssh [www.cs.hut.fi SSH] — Secure Shell. Пакет представляет собой функциональную замену программ rlogin/rsh и соответствующего этим программам демона rshd. В пакет входят программы ssh (клиент) и sshd (сервер), а также утилиты для генерации ключей RSA и управления ими. ssh использует RSA для прозрачной аутентификации пользователя при входе в удаленную систему. Кроме того, ssh/sshd могут осуществлять шифрование данных, передаваемых по линии во время сеанса связи и выполнять ряд других полезных функций.
Сервер хранит список известных общедоступных ключей для каждого из пользователей в файле SHOME/.ssh/authorized_keys, где $НОМЕ обозначает домашний каталог пользователя. Файл состоит из строк формата host_name: key— по строке для каждого из разрешенных клиентов. В свою очередь, каждый клиент хранит в файле $HOME/.ssh/private_key свой приватный ключ.
Когда из удаленной системы-клиента приходит запрос на аутентификацию, sshd запрашивает публичный ключ. Если полученный ключ совпадает с хранящимся в файле значением для этой системы, сервер генерирует случайную последовательность из 256 бит, шифрует ее публичным ключом и посылает клиенту. Клиент расшифровывает посылку своим личным ключом, вычисляет 128-битовую контрольную сумму и возвращают ее серверу. Сервер сравнивает полученную последовательность с правильной контрольной суммой и принимает аутентификацию в случае совпадения (рис. 12.5). Теоретически контрольные суммы могут совпасть и в случае несовпадения ключей, но вероятность такого события крайне мала.

Рис. 12.5. Аутентификация SSH

Аутентификация Lotus Notes
Система групповой работы Lotus Notes также использует для аутентификации открытый ключ. При создании учетной записи пользователя генерируются 621-битный приватный и соответствующий ему публичный ключи. Публичный ключ размещается в доменной адресной книге (рис. 12.6). Приватный ключ подвергается шифрованию закрытым ключом, который потом запрашивается у пользователя в качестве пароля, и сохраняется в идентификационном файле.

Рис. 12.6. Аутентификация в Lotus Notes

Чтобы аутентифицироваться в системе, пользователь должен указать идентификационный файл и набрать пароль, который позволит расшифровать хранящийся в файле приватный ключ. После этого все пакеты, которыми пользователь обменивается с сервером Notes, снабжаются цифровой подписью на основе этого ключа. Сервер может проверить аутентичность подписи, используя хранящийся в его адресной книге публичный ключ.
Более сложная ситуация возникает, когда пользователь должен аутентифицироваться в другом домене, в адресных книгах которого он не числится. Чтобы сделать такую авторизацию возможной, Notes вводит еще одно понятие: сертификат домена. Этот сертификат также представляет собой пару ключей, пароль к приватному ключу которой известен только администраторам домена. Каждый идентификационный файл, создаваемый в домене, подписывается приватным ключом этого сертификата (рис. 12.7).
Регистрируясь в чужом домене, пользователь предъявляет свои имя и публичный ключ, подписанные сертификатом своего домена. Если принимающий домен не знает такого сертификата, аутентификация отвергается. Чтобы домен мог признать чужой сертификат, его администратор должен провести кросс-сертификацию, а попросту говоря создать в доменной адресной книге документ, в котором хранится публичный ключ сертификата домена [redbooks.ibm.com sg245341] (рис. 12.8).

Рис. 12.7. Сертификат домена Lotus Notes

Рис. 12.8. Кросс-сертификация между доменами Lotus Notes

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

Авторизация

  Иннокентий на кухне, он пьет молоко
Таракана завидев во мраке
На душе его чисто, светло и легко
Он не хочет впускать Полтораки
Б. Гребенщиков
Механизмы авторизации в различных ОС и прикладных системах различны, но их трудно назвать разнообразными. Два основных подхода к авторизации — это ACL (Access Control List, список управления доступом) или список контроля доступа и полномочия (capability).
Список контроля доступа ассоциируется с объектом или группой объектов и представлет собой таблицу, строки которой соответствуют учетным записям пользователей, а столбцы — отдельным операциям, которые можно осуществить над объектом. Перед выполнением операции система ищет идентификатор пользователя в таблице и проверяет, указана ли выполняемая операция в списке его прав.
Реализация списков управления доступом вполне прямолинейна и не представляет непреодолимых сложностей. Разработчики системы безопасности, впрочем, могут (и часто бывают вынуждены) предпринимать достаточно сложные меры для сокращения ACL, предлагая те или иные явные и неявные способы объединения пользователей и защищаемых объектов в группы.
Полномочие представляет собой абстрактный объект, наличие которого в контексте доступа задачи позволяет выполнять ту или иную операцию над защищаемым объектом или классом объектов, а отсутствие — соответственно,
не позволяет. При реализации такой системы разработчик должен гарантировать, что пользователь не сможет самостоятельно сформировать полномочие.
Например, полномочие может быть реализовано в виде ключа шифрования или электронной подписи. Невозможность формирования таких полномочий обеспечивается непомерными вычислительными затратами, которые нужны для подбора ключа.

 

Списки контроля доступа

  — Что это?— вытянул шею Гмык, хмуро глядя на мои карты. — Но тут ,же только.
— Минутку, — вмешался игрок слева от него. — Сегодня вторник. Выходит, его единороги дикие.
— Но в названии месяца есть "М"— вякнул еще кто-то. — Значит, его великан идет за половину номинальной стоимости!
— Но у нас четное число игроков...
— Вы все кое-что упускаете. Эта партия — сорок третья, а Скив сидит на стуле лицом к северу!
Приняв за указание стоны и все заметнее вырисовывавшееся выражение отвращения на лицах, я сгреб банк.
Р. Асприн

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

Рис. 12.9. Список контроля доступа

Есть три основных подхода, используемых для сокращения ACL.

Использование прав по умолчанию Группирование пользователей и/или объектов Ограничение комбинаций прав, которыми пользователи и группы могут реально обладать

Права по умолчанию дают наибольший эффект тогда, когда большая часть прав большинства пользователей на большинство объектов одинакова. Чаще всего рекомендуют при установлении прав исходить из принципа "запрещено все, что не разрешено [явным образом]" — при последовательном его применении должно получаться, что большинство пользователей не имеет прав на подавляющую часть объектов в системе. Исходя из этого, в большинстве систем пользователи, явно или неявно не перечисленные в ACL объекта, не имеют на объект никаких прав. Многие системы также предоставляют специальную запись в ACL, соответствующую пользователям, которые не перечислены явно.
Объединение пользователей в группы представляет собой более универсальное средство, которое полезно не только для сокращения ACL, но и для других целей. Группа вводит дополнительный уровень косвенности (ACL ссылается на пользователя не прямо, а косвенно, через группу в систему установления прав и управления ими, и это дает дополнительную гибкость, полезную во многих практических случаях (рис. 12.10).

Рис. 12.10. Группы пользователей

Так, в большинстве случаев полномочиями наделяют человека не за то, что он такой хороший, а потому, что они нужны ему для выполнения служебных обязанностей. Изменение служебных обязанностей (постоянное, при переходе на другую должность, или временное, например, при замене заболевшего или ушедшего в отпуск сотрудника) сопровождается изменением прав, которыми пользователь должен обладать.
В этой ситуации целесообразно создать группу, соответствующую той или иной должности, и выдавать права на объекты этой группе. Назначение человека на должность сопровождается включением его в соответствующую группу, а снятие — исключением из нее. Без использования групп эти операции потребовати бы явной модификации ACL всех объектов, права на которые изменяются, что во многих случаях совершенно нерационально.
Группы яшшотся практически обязательным элементом систем упраатения правами на основе списков. Большинство систем предоставляет возможность создания вложенных групп (рис. 12.11). Ряд современных систем (Novell Netware 4..Y, Windows 2000, Solans 6) предоставляют также иерархические структуры БД учетных записей, почему-то называемые службами каталогов (NDS -Netware Directory Service в Netware, Active Directory в Windows, NIS+ - - Network Information Service в Solans). Впервые служба каталогов была реализована в сетевой ОС VINES (Virtual NEtwork Services) фирмы Banyan Systems в конце 80-х.

Рис. 12.11. Вложенные группы и структура организации

Иерархическая структура особенно удобна для больших организаций, потому что она не только обеспечивает "естественную" структуру вложенных групп, но и облегчает просмотр учетных записей и управление ими.
При активном использовании групп пользователей может возникнуть специфическая проблема: пользователь может состоять в нескольких группах и иметь собственную запись в ACL и, таким образом, получать права на объект несколькими путями (рис. 12.12). Строго говоря, проблемой это не является, важно лишь описать, что будет происходить с правами в этом случае. В различных системах используются почти все мыслимые варианты поведения.

Рис. 12.12. Получение прав из нескольких групп

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

Наследование прав на файлы в Novell Netware
По-видимому, наибольшей сложности группирование объектов достигло в системе Novell Netware. Рассмотрим схему установления прав на файлы в этой ОС.
Запись файлового ACL в Netware представляет собой битовую маску, значения разрядов которой перечислены в табл. 12.1. Видно, что некоторые из прав имеют смысл только для файлов, а некоторые — только для каталогов.
Каталоги и файлы в этой системе наследуют права доступа от родительских каталогов. Если пользователь или группа не перечислены явно в ACL объекта, их эффективные права будут определяться записями в ACL родительских каталогов (рис. 12.13). Если пользователь перечислен в ACL родительского и дочернего каталогов, его эффективные права будут равны сумме прав, указанных в обеих записях. Таким образом, по мере спуска по дереву каталогов, эффективные права могут только возрастать.

Рис. 12.13. Наследование прав на каталоги в Novell Netware (обозначения прав соответствуют табл. 12.1)

При этом пользователь не обязан иметь права на каталог, чтобы видеть его файлы и подкаталоги. Поэтому система управления доступом Netware предполагает выдачу прав как можно ближе по дереву каталогов к тем файлам, права на которые необходимы. Права на корневые каталоги томов обычно выдаются только администратору системы.
В случае если все-таки потребуется изменить принцип расширения прав по мере спуска по дереву, каталоги и файлы, кроме ACL, имеют дополнительный атрибут, называемый IRF (Inherited Rights Filter— фильтр наследуемых прав). Этот атрибут представляет собой битовую маску, биты которой (кроме бита S — он не может быть отфильтрован) соответствуют битам записи ACL (см. табл. 12.1). Установка бита в этой маске приводит к блокировке наследования соответствующего права (рис. 12.14).

Рис. 12.14. Фильтр наследуемых прав в Novell Netware

Запрет на фильтрацию права супервизора обусловлен тем, что его включение по ошибке приведет к потере администратором прав на эту иерархию. Избавиться от такого поддерева можно было бы только переразметкой тома.
В пользовательской базе данных, которая, начиная с Netware 4.x, также имеет иерархическую структуру, и наследование, блокирование супервизорских прав разрешено, поэтому можно по ошибке "даровать суверенитет" ветви дерева (рис. 12.15). Это одна из распространенных ошибок начинающих администраторов. В административных утилитах Netware 4.11 даже была введена специальная проверка, не позволяющая отфильтровать право супервизора, если ни у кого нет явно выданных супервизорских прав на соответствующий контейнер или объект.

Рис. 12.15. Дарование суверенитета ветви дерева каталогов

Таблица 12.1. Права доступа к файлу в Novell Netware 3.x и выше

Бит
Обозначение
Описание
S
Supervisor
Право осуществлять любые операции над файлом или каталогом
А
Access
Право модифицировать ACL файла или каталога
R
Read
Право читать файл
С
Create
Право создавать файлы в каталоге
W
Write
Право записи в файл
Е
Erase
Право удалять файл или каталог
М
Modify
Право изменять атрибуты файла или каталога
F
Find
Право на поиск файлов в каталоге

Альтернативой этим хитростям является третий из упомянутых путей -ограничение комбинаций прав, которые реально могут быть выданы. С одним из примеров такого ограничения мы сталкивались в разд. Сегменты, страницы и системные вызовы : диспетчер памяти VAX имеет четыре уровня привилегий, каждый из которых может иметь право чтения и записи в страницу памяти. Все возможные комбинации прав в этих условиях кодируются 8-ю битами, но наложение требования о том, что каждый более высокий уровень обязан иметь хотя бы те же права, что и более низкие, позволяет нам обойтись 15-ю допустимыми комбинациями и 4-мя битами для их кодирования.
При разработке такой системы мы сталкиваемся с нетривиальной задачей: нам нужно выработать такие ограничения, которые не только обеспечивали бы компактное представление ACL, но и позволяли так или иначе реализовать комбинации прав, необходимые для практической эксплуатации вычислительных систем.
Замечательным примером ограниченного ACL, структура которого выдержала 30-летнюю проверку практикой, является модель безопасности в системах семейства Unix.

Авторизация в Unix
В этих системах ACL состоит ровно из трех записей (рис. 12.16).
Права хозяина файла (пользователя)
Права группы
Права по умолчанию

Рис. 12.16. Установление прав в системах семейства Unix

Как правило, права хозяина выше прав группы, а права группы выше прав по умолчанию, но это не является обязательным требованием и никем специально не проверяется. Пользователь может принадлежать к нескольким группам одновременно, файл всегда принадлежит только одной группе.
Бывают три права: чтения, записи и исполнения. Для каталога право исполнения означает право на открытие файлов в этом каталоге. Каждое из прав обозначается битом в маске прав доступа, т. е. все три группы прав представляются девятью битами или тремя восьмеричными цифрами.
Права на удаление или переименование файла не существует; вообще, в Unix не определена операция удаления файла как таковая, а существует лишь операция удаления имени unlink. Это связано с тем, что файл в Unix может иметь несколько имен, и собственно удаление происходит только при уничтожении последнего имени (подробнее см. главу 11). Для удаления, изменения или создания нового имени файла достаточно иметь право записи в каталог, в котором это имя содержится.
Удаление файлов из каталога, в действительности, можно в определенных пределах контролировать: установка дополнительного бита (маска прав содержит не девять, а двенадцать бит, с семантикой еще двух из них мы познакомимся в разд.

Полномочия

  Ты пришли ко мне утром, ты cела на кровать
Ты спросила, есть ли у меня разрешение
дышать
И действителен ли мой пропуск
Чтобы выйти в кино
Б. Гребенщиков

В чистом виде модель авторизации на основе полномочий реализована в системах Burroughs и Intel 432, которые подробнее рассматриваются в разд. Сегменты, страницы и системные вызовы и Взаимно недоверяющие подсистемы. Полномочия доступа к сегментам единого адресного пространства в этих системах реализованы в виде полей селектора сегмента или мандатов, а невозможность самостоятельной их генерации пользователем обеспечена тэговой архитектурой и запретом арифметических операций над сегментной частью указателя.
Системы с моделями безопасности, основанные на одних лишь полномочиях, не имели коммерческого успеха. Однако концепция полномочий распространена гораздо шире, чем это принято думать. Так, реализация модели безопасности на основе ACL возможна лишь постольку, поскольку системные модули имеют полномочия делать что угодно, не обращаясь ни к каким ACL (в частности, и полномочия выполнять перечисленные в ACL операции), а пользовательский код таких полномочий не имеет. В силу этого, пользователь может выполнять необходимые ему операции лишь посредством обращения к системным модулям.
Только в этих условиях проверка ACL перед входом в системный модуль имеет смысл — если бы пользователь мог бы выполнить операцию сам или вызывать системные подпрограммы без ограничений, обход любого ACL выполнялся бы очевидным образом.
В частности, поэтому в системах с открытой памятью невозможны сколько-нибудь эффективные средства управления доступом: пользователь имеет возможность выполнять любые операции самостоятельно, а при использовании криптографической защиты может похитить ключ или модифицировать алгоритм шифрования.
Типичная практически используемая архитектура управления доступом предоставляет пользователю и системному администратору управление правами в форме списков контроля доступа и содержит один или несколько простых типов полномочий, чтобы предотвратить доступ в обход этих списков. Простейшей структурой таких полномочий является разделение пользовательского и системного режимов работы процессора и исполнение всего не пользующегося доверием кода в пользовательском режиме.
Системный режим процессора является полномочием или, во всяком случае, может применяться в качестве такового: обладание им позволяет выполнять операции, недопустимые в пользовательском режиме, и этот режим не может произвольно устанавливаться. Он позволяет реализовать не только ACL, но и дополнительные полномочия: пользователь не имеет доступа в системное адресное пространство, поэтому система может рассматривать те или иные атрибуты дескриптора пользовательского процесса как полномочия (рис. 12.18).
Идентификатор пользователя, устанавливаемый при аутентификации и хранящийся в дескрипторе процесса в адресном пространстве ядра, также может рассматриваться как полномочие. Для того чтобы этот идентификатор действительно можно было использовать таким образом, необходимо ввести весьма жесткие ограничения на то, кто и каким образом может производить аутентификацию.
Два подхода к решению этой задачи — это осуществление аутентификации модулями ядра и введение специального идентификатора пользователя (или специального типа процессов).

Рис. 12.18. Хранение полномочий в системном адресном пространстве

Включение средств аутентификации в ядро кажется весьма привлекательным: мы можем быть уверены, что никто не получит чужие полномочия, иначе как пройдя штатную процедуру проверки идентичности. С другой стороны, каждый процесс, считающий, что ему следует произвести смену идентичности (например, сервер, исполняющий запрос от имени конкретного пользователя) может запросить у пользователя имя и пароль и переау-тентифицироваться без каких-либо трудностей.
Проблема при таком подходе состоит в том, что мц ограничиваем используемые в системе способы аутентификации и форматы пользовательской базы данных.
Разработка модулей, реализующих альтернативные способы аутентификации (например, применяющих папиллярный детектор или сканер глазного дна вместо запроса пароля) или нестандартные способы хранения списков пользователей резко усложняются — теперь это должны быть не простые разделяемые библиотеки, а модули ядра.
Осуществление аутентификации в пользовательском режиме требует введения специального [псевдо]пользователя, которому разрешено становиться другими пользователями (или, говоря точнее, приобретать их идентичность) или специального типа процессов, которые могут делать это. Привилегия входить в систему и запускать процессы с таким идентификатором должна жестко контролироваться: ведь обладатель таких полномочий может стать кем угодно и, таким образом, выполнять любое действие, которое кому-либо разрешено.

Аутентификация в Unix
В системах семейства Unix процессы с эффективным пользовательским идентификатором, равным 0, имеют право исполнять системные вызовы setuid и setgid и, таким образом, становиться другими пользователями. Другие пользователи не имеют такой возможности, поэтому все процессы, в той или иной форме, осуществляющие аутентификацию и смену идентичности, как с применением стандартных системных средств (файлов /etc/passwd и /etc/shadow в старых системах и разделяемых библиотек РАМ в современных), так и самостоятельно, обязаны исполняться от имени этого пользователя.
Поскольку пользователь с идентификатором 0 (root) может приобретать идентичность других пользователей, он, как уже говорилось, фактически обладает всеми правами, которые есть у кого бы то ни было другого в системе. Признав этот факт, разработчики Unix явным образом дали пользователю root вообще все права, в том числе и такие, которых не имеет никто другой.
Мы уже отмечали в разд.

Изменение идентификатора пользователя

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

Авторизация доступа к полям документа в Notes
Программный комплекс Lotus Notes, широко признанный как лучшая основа для реализации систем документооборота, позволяет устанавливать права на отдельные поля или группы полей документа, а стандартная техника реализации вышеприведенных требований состоит в том, чтобы сначала предоставить пользователю право записи в поле, где должна быть подпись, а потом — после подписания — это право тут же снять. Впрочем, при реализации сложных циклов документооборота, включающих много взаимосвязанных документов, нередко возникают ситуации, неразрешимые с помощью только этих средств [Керн/Линд 2000].

Можно привести и другой пример, более тесно связанный с темой книги: для изменения информации о пользователе необходим доступ для записи в соответствующую базу данных, но не во всю, а только в определенную запись. Вполне естественно и даже необходимо дать пользователю возможность менять пароль, не обращаясь к администратору. С другой стороны, совершенно недопустимо, чтобы один пользователь, не являясь администратором учетных записей, мог сменить пароль другому.
Одним из решений было бы хранение пароля для каждого из пользователей в отдельном файле, но это во многих отношениях неудобно. Другое решение может состоять в использовании модели клиент-сервер с процессом-сервером, исполняющимся с привилегиями администратора, который является единственным средством доступа к паролям. Например, в Win32 весь доступ к пользовательской базе данных осуществляется через системные вызовы, т. е. функции процесса-сервера исполняет само ядро системы.
В системах семейства Unix для этой цели был предложен оригинальный механизм, известный как setuid (setting of user id - установка [эффективного] идентификатора пользователя). По легенде, идея этого механизма возникла именно при решении задачи о том, как же пользователи смогут менять свои пароли, если их хэши будут храниться в одном файле.

Установка идентификатора пользователя в Unix
В Unix каждая задача имеет два пользовательских идентификатора: реальный и эффективный. Реальный идентификатор обычно совпадает с идентификатором пользователя, запустившего задание. Для проверки прав доступа к файлам и другим объектам, однако, используется эффективный идентификатор. При запуске обычных задач реальный и эффективный идентификаторы совпадают. Несовпадение может возникнуть при запуске программы с установленным признаком setuid. При этом эффективный идентификатор для задачи устанавливается равным идентификатору хозяина файла, содержащего программу.
Признак setuid является атрибутом файла, хранящего загрузочный модуль программы. Только хозяин может установить этот признак, таким образом, передавая другим пользователям право исполнять эту программу от своего имени. При модификации файла или при передаче его другому пользователю признак setuid автоматически сбрасывается.
Например, программа /bin/passwd, вызываемая для смены пароля, принадлежит пользователю root, и у нее установлен признак setuid. Любой пользователь, запустивший эту программу, получает задачу, имеющую право модификации пользовательской базы данных, — файлов /etc/passwd и /etc/shadow. Однако, прежде чем произвести модификацию, программа passwd проверяет допустимость модификации. Например, при смене пароля она требует ввести
старый пароль (рис. 12.20). Сменить пароль пользователю, который его забыл, может только root.
Другим примером setuid-программы может служить программа /bin/ps (process status — состояние процессов) в старых системах. До установления стандарта на псевдофайловую систему /proc, Unix не предоставляла штатных средств для получения статистики об исполняющихся процессах. Программа /bin/ps в таких системах анализировала виртуальную память ядра системы, доступную как файл устройства /dev/kmem, находила в ней список процессов и выводила содержащиеся в списке данные. Естественно, только привилегированная программа может осуществлять доступ к /dev/kmem.

Рис. 12.20. Смена идентификатора пользователя в Unix

Механизм setuid был изобретен одним из отцов-основателей Unix, Деннисом Ритчи, и запатентован компанией AT&T в 1975 г. Через несколько месяцев после получения патента, ему был дан статус public domain. Официально AT&T объяснила это тем, что плату за использование данного патента нецелесообразно делать высокой, а сбор небольшой платы с большого числа пользователей неудобен и тоже нецелесообразен.
Механизм setuid позволяет выдавать привилегии, доступные только суперпользователю, как отдельным пользователям (при этом setuid-программа должна явным образом проверять реальный идентификатор пользователя и сравнивать его с собственной базой данных), так и группам (при этом достаточно передать setuid-программу соответствующей группе и дать ей право исполнения на эту программу), таким образом, отчасти компенсируя недостаточную гибкость стандартной системы прав доступа и привилегий в системе Unix.

Серверные агенты в Notes
До совершенства механизм setuid доведен в Lotus Notes (этот пакет относится к прикладным программам, а не операционным системам, но реализует собственные схемы аутентификации и авторизации). В этой системе все объекты базы данных, в том числе и агенты (хранимые процедуры), снабжены электронной подписью. Серверные агенты исполняются не от имени пользователя, инициировавшего операцию, а от имени того, кем агент подписан. В данном случае подпись кода означает, что либо пользователь сам занимался разработкой агента, либо он явным образом согласился взять на себя ответственность за результаты его работы. Подпись подделать практически невозможно (используется алгоритм RSA с 631-битным ключом) [redbooks.ibm.com sg245341].


Ресурсные квоты

  Мне больно видеть белый свет,
Мне лучше в полной темноте
Я очень много-много лет
Мечтаю только о ede
A. Kнязев

Все ресурсы, управление которыми осуществляет операционная система, -дисковое пространство, оперативная память, время центрального процессора, пропускная способность внешних соединений и т. д. — с одной стороны, конечны и, таким образом, исчерпаемы, а с другой — стоят денег.
Необоснованное расходование того или иного ресурса пользователем может привести к его исчерпанию и лишению других пользователей системы доступа к нему. Если ресурс необходим для работы системы, в результате последняя станет неработоспособной. Такое расходование может происходить как просто по ошибке, так и в рамках целенаправленной атаки на вычислительную систему. Промежуточное положение между этими случаями занимает использование корпоративных вычислительнВ1х ресурсов в личных целях: даже если политика компании и допускает это, те или иные пределы такому использованию необходимо установить именно в силу ограниченности ресурса.
Стандартным способом предотвратить исчерпание ресурсов в масштабах системы является введение квот (quota) на эти ресурсы: ограничений количества ресурса, которое конкретный пользователь может занять. Иногда квоты выделяются не отдельным пользователям, а группам, но — из-за возникающей при этом проблемы разрешения ресурсных конфликтов между пользователями группы -- это делается очень редко. Практически всегда квота выделяется отдельному пользователю.
Чаще всего квотированию подвергается дисковое пространство. В системах семейства Unix, в которых большинство файловых систем используют статические таблицы инодов, квотированию подлежит также количество файлов, которые могут принадлежать данному пользователю.
В системах коллективного пользования квоты устанавливаются практически на все ресурсы: объем адресного пространства и рабочего множества страниц отдельной пользовательской задачи, количество одновременно запущенных процессов, время исполнения отдельной задачи или суммарное занятое время центрального процессора и т. д. Объясняется это тем, что любой ресурс, который пользователь может занимать неограниченно, представляет собой потенциальную точку атаки на безопасность системы. На практике квоты многих ресурсов могут устанавливаться весьма высокими, так что пользователь при разумном применении системы может никогда с ними не столкнуться.
Особую роль квоты играют в вычислительных системах, совместно используемых несколькими организациями, — в этом случае квоты ресурсов, выделяемых пользователям соответствующих организаций, могут быть пропорциональны сумме денег, которые организация вносит за пользование системой. Предельным случаем систем такого рода являются ISP (Internet Service Providers, поставщики услуг Интернет), которые предоставляют ресурсы (внешние каналы и телефонные линии, дисковое пространство для почтовых ящиков и домашних страниц) мелким организациям и индивидуальным пользователям. Организованные по тем же принципам ASP (Application Service Providers, поставщики услуг приложений) на момент написания этой книги не имели большого успеха, однако есть много оснований предполагать значительное развитие этого бизнеса в будущем.


Атаки на систему безопасности

  Вместо роллингов — хакеры
Вместо битлов — юзера
Б. Гребенщиков

Как видно из разд.

Отказ в сервисе

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


Троянские программы

  Не верьте данайцам, дары приносящим.
Гомер


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

Пример троянской программы
Простой и по-своему элегантный пример троянской программы приводится во многих учебниках по командному языку систем семейства Unix, например в [Керниган/Пайк 1992]. В указанной работе эта программа приводится для объяснения того, почему в Unix путь поиска исполняемых программ по умолчанию не включает текущего каталога, и почему включать текущий каталог в этот путь крайне нежелательно.
Программа из примера 12.1 работает следующим образом.
1. Вредитель помещает ее в общедоступный каталог под именем Is.
2. Пользователь входит в этот каталог и исполняет команду Is (просмотр текущего каталога).
3. Вместо системной команды /bin/Is исполняется троянская программа.
4. Троянская программа совершает вредоносное действие и запускает настоящий /bin/Is, позаботившись о том, чтобы отфильтровать свою запись из листинга каталога.

Пример 12.1. Троянская программа на языке shell

#!/bin/sh
# Разместите эту программу в общедоступном каталоге и назовите ее Is
# Скопировать себя в домашний каталог пользователя;
# на этом месте может стоять и другая вредоносная операция ср $0 ~
/bin/Is $# | /home/badguy/filter_ls $#

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

Троянская программа может быть реализована не только в виде самостоятельного загрузочного модуля, но и в виде разделяемой библиотеки. Так, в Windows NT 4.0 вплоть до выхода Service Pack 5 присутствовала ошибка, позволявшая зарегистрировать DLL, совпадающую по имени с любой из системных, причем так, чтобы при разрешении ссылок из других модулей использовалась вновь зарегистрированная библиотека.

Аналогичный пример для Win32
Уже во время подготовки книги к печати началась пандемия вируса Nimda, один из приемов распространения которого аналогичен приведенному в примере 12.1: обнаружив каталог, в котором лежат файлы данных MS Office, вирус помещает туда файл riched20.dll. При сборке программы в момент запуска, Windows просматривает текущий каталог до перечисленных в PATH, поэтому вместо модуля Office загружается троянский код вируса. В отличие от систем семейства Unix, в Win32 порядок просмотра каталогов при сборке жестко задан и не поддается контролю со стороны системного администратора, поэтому перекрыть данный путь распространения заразы можно лишь модификацией ядра Windows.

Многие троянские программы образуются модификацией присутствующих в системе загрузочных модулей, разделяемых библиотек и даже модулей ядра.
Такая программа не обязательно должна представлять собой бинарный код — это может быть также интерпретируемый код или последовательность команд макропроцессора. Широко распространены макровирусы, распространяющиеся с файлами данных пакета Microsoft Office.
Наиболее известны два специальных типа троянских программ, часть вредоносных действий которых состоит в дальнейшем их распространении, а именно вирусы и черви. Вирусы предполагают целенаправленный запуск зараженной программы пользователем, черви же, проникнув в систему, запускают собственный процесс размножения.
Широко распространенные в эпоху DOS бинарные вирусы просто добавляют свой код ко всем исполняемым модулям, которые так или иначе оказываются в сфере досягаемости запущенной копии вируса.
Промежуточное с точки зрения классификации между собственно вирусами и червями занимают загрузочные вирусы, которые размещаются в загрузочных секторах дисковых устройств. Загрузочный вирус регистрирует себя в качестве драйвера дискового устройства и остается -жить в системе, заражая все подключаемые к системе удаляемые носители (дискеты, Zip-диски, болванки CD-ROM). Загрузка — чаще всего, по ошибке — другой системы с зараженной дискеты приводит к заражению новой системы. В современных ОС с их многоэтапной загрузкой и сложными архитектурами драйверов загрузочные вирусы представляют несколько меньшую опасность, чем в эпоху MS DOS.
Черви способны размножаться без участия пользователей системы. Заражению червями подвержены лишь многопоточные ОС с более или менее развитыми сетевыми сервисами. Заразив систему, червь запускает себя в качестве фонового процесса и начинает атаку других систем, используя фиксированный набор известных проблем в их системах безопасности. Нередко червь в обязательном порядке заражает системы, которые доверяют зараженной или просто используют общую с нею базу учетных записей — например, заразив одну из систем домена Windows NT от имени администратора системы, червь может штатными средствами установить себя на все остальные системы того же домена.
Вирусы и черви доставляют много неприятностей сами по себе, к тому же их авторы часто не отличаются большой фантазией в выборе деструктивных действий и просто уничтожают все или только наиболее важные данные в зараженных системах.
Важно подчеркнуть, что если ваша сеть подвержена вирусным атакам, или же если единственной защитой вашей сети от них служит антивирусный пакет, способный только находить известные вирусы, она будет столь же уязвима и для троянских программ, специально разработанных с целью атаки на данные вашей организации, и, таким образом, вашу систему безопасности следует признать абсолютно непригодной.

Типичные уязвимые места

  Ты намерен потопишь корабль?- уточнил он. На лице Смерти отразился ужас.
РАЗУМЕЕТСЯ, НЕТ. БУДЕТ ИМЕТЬ МЕСТО СОЧЕТАНИЕ НЕУМЕЛОГО УПРАВЛЕНИЯ КОРАБЛЕМ, НИЗКОГО УРОВНЯ ВОДЫ И ПРОТИВНОГО ВЕТРА.
Т. Пратчетт

Современные системы общего назначения имеют развитую систему безопасности, основанную на сочетании ACL и полномочий. Методы получения и передачи полномочий в этих ОС, как правило, теоретически корректны в том смысле, что доказана невозможность установления полномочия для пользователя или процесса, который не должен этого полномочия получать (сказанное не относится к системам Windows 95/98/ME, в которых эффективные средства безопасности отсутствуют по проекту).
В таких системах существует пять основных источников проблем безопасности.

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

Первый источник проблем преодолим только организационными мерами, и лишь некоторые из них — например, проведение с пользователями воспитательной работы — находятся в сфере компетенции системного администратора. Исключение составляет борьба с прослушиванием сети: предотвращение технической возможности несанкционированного подключения к сети также обычно находится на грани области компетенции системного администратора, но использование шифрованных сетевых протоколов или хотя бы таких, в которых имя и пароль передаются в хэшированием виде, может значительно уменьшить пользу прослушивания для злоумышленника.
Второй источник также следует преодолевать организационными мерами. Разумной политикой, по-видимому, следует считать не полный запрет компьютерных игр, а постановку процесса под контроль путем создания легального более или менее централизованного хранилища этих игр, систематически проверяемого на предмет "заразы". Поддержание этого хранилища может выполняться как самим системным администратором, так и на общественных началах.
Третий источник проблем находится преимущественно в голове самого системного администратора. Он должен знать точную семантику записей в ACL используемой ОС, исключения из правил, хотя бы наиболее распространенные стандартные ошибки, а также то, какие и кому права даются по умолчанию.
Большую помощь в формировании оптимальных и безошибочных ACL и групп оказывает хорошо документированная организационная структура компании, из которой ясно, какие служебные обязанности требуют того или иного доступа к тем или иным ресурсам и почему, и на основании каких распоряжений тот или иной уровень доступа должен быть изменен. Сверх этого можно надеяться только на аккуратность и привычку к систематической мыслительной деятельности.
Ни в коем случае не следует полагаться на то, что права, раздаваемые системой или прикладным пакетом по умолчанию, адекватны и могут быть оставлены без изменения. Так, в Windows NT/2000/XP на разделяемый дисковый ресурс по умолчанию даются права Everyone:Full Control (т. е. всем пользователям, явно не перечисленным в ACL, даются все права, в том числе и на изменение прав).
Четвертый источник, как правило, находится вне контроля системного администратора: хотя он и может иметь право голоса в решении вопроса о судьбе таких систем, но обычно его голос не оказывается решающим. Если отсутствие или неадекватность средств безопасности в операционной системе настольного компьютера часто можно скомпенсировать, исключив хранение на нем чувствительных данных, не запуская на нем доступных извне сервисов и — в пределе — сведя его к роли малоинтеллектуального конечного устройства распределенной системы, а его локальный диск — к роли кэша программ и второстепенных данных, то с приложениями все гораздо хуже.
Используемые в организации приложения и, что самое главное, стиль их использования обычно обусловлены ее бизнес-процессом, поэтому недостаточно продуманные попытки не только миграции в другое приложение, а иногда и установка patches (заплат) или изменения настроек могут привести к нарушениям в бизнес-процессе. Тщательное же продумывание и аккуратная миграция представляет собой сложный, весьма дорогостоящий и все-таки рискованный процесс, на который руководство организации всегда -по очевидным причинам — идет крайне неохотно. Это в равной мере относится как к мелким конторам с "документооборотом" на основе MS Office, так и к организациям, в которых основное бизнес-приложение представляет собой самостоятельно разрабатываемый и поддерживаемый программно-аппаратный комплекс, сохраняющий преемственность по данным с самим собой с конца XIX века (без шуток — механизированные системы обработки данных, табуляторы Холлерита, появились уже тогда).
В то же время, некоторые распространенные приложения представляют собой настоящий рай для взломщика, настолько богатый возможностями, что многие взломщики из спортивного интереса даже считают ниже своего достоинства этими возможностями пользоваться. Речь прежде всего идет о почтовом клиенте Microsoft Outlook, который без всяких предупреждений (а старые версии и автоматически) запускает пришедшие по почте исполняемые файлы.
Не менее чудовищна модель безопасности приложений пакета Microsoft Office, в которых документ может содержать макропрограммы, в том числе и способные модифицировать файлы, не имеющие отношения к документу. Новые версии пакета содержат средства, позволяющие в определенных пределах контролировать исполнение этих макропрограмм, но крайняя непродуманность этих средств вынуждает многих пользователей отключать их.
Указанные приложения являются идеальной средой для распространения вирусов и других троянских программ. Антивирусные пакеты ни в коем случае не могут считаться адекватной мерой, потому что обнаруживают только известные вирусы, обнаружить же новый вирус или троянскую программу, написанную специально для доступа к данным вашей компании, они принципиально не способны. Автор не в состоянии предложить эффективного способа действий при использовании в компании этих приложений, и может лишь посоветовать все-таки принудительно выключить макросы в
приложениях Office и научить пользователей не открывать незнакомые фай-I лы, пришедшие по почте.
Наконец, пятая причина — ошибки в модулях ОС и приложениях — хотя и находится за пределами непосредственной сферы влияния системного администратора, но заслуживает более подробного обсуждения, особенно потому, что мы предназначаем нашу книгу не только эксплуатационщикам, но и разработчикам программного обеспечения.


Ошибки программирования

Хотя мы и утверждали в начале предыдущего раздела, что методы управления полномочиями в современных ОС общего назначения теоретически идеальны, это относится лишь к идеальной ОС, т. е. к спецификациям соответствующих модулей. В то же время, в реальном коде встречаются отклонения от спецификаций, так называемые ошибки. Полный обзор и исчерпывающая классификация всех практически встречающихся типов ошибок, по-видимому, невыполнимы. В этом разделе мы опишем только наиболее распространенные и наиболее опасные ошибки.
Наибольшую опасность с точки зрения безопасности представляют ошибки в модулях, связанных с проверкой ACL, авторизацией и повышением уровня привилегий процессора (например, в диспетчере системных вызовов), а в системах семейства Unix — в setuid-программах.
Одна из наиболее опасных — и в то же время довольно распространенная в современных программах — ошибка приведена в примере 2.4. Рассмотрим этот код еще раз (пример 12.2).

Пример 12.2. Пример программы, подверженной срыву стека

/* Фрагмент примитивной реализации сервера SMTP (RFC822) */
int parse_line(FILE * socket)
{
/* Согласно RFC822, команда имеет длину не более 4 байт,
а вся строка — не более 255 байт */
char cmd[5], args[255];
fscanf(socket, "%s %s\n", and, args);
/* Остаток программы нас не интересует */

Видно, что наша программа считывает из сетевого соединения строку, которая должна состоять из двух полей, разделенных пробелом, и заканчиваться символом перевода строки. В соответствии со спецификациями протокола SMTP, первое поле (команда) не может превышать четырех символов (к сожалению, не определено в протоколе более длинных команд), а строка целиком не может быть длиннее 255 байт.
Если наш партнер на другом конце соединения полностью соответствует требованиям fRFC 0822], наш код будет работать без проблем. Проблемы — причем серьезнейшие — возникнут, если нам передадут строку, которая этим требованиям не соответствует.
Превышение допустимой длины кодом команды не представляет большой опасности: лишние байты будут записаны в начало массива args и потеряны при записи в него его собственного поля. Настоящая опасность — это превышение длины всей строки. Для нашего партнера не представляет никаких сложностей сгенерировать последовательность из более чем 255 символов, не содержащую переводов строки (рис. 12.21).

Рис. 12.21. Срыв буфера

Тогда буфер arg переполнится, но за ним в памяти следует вовсе не другой буфер, а — ни много, ни мало, заголовок стекового кадра, в котором содержится адрес возврата нашей подпрограммы. Важно подчеркнуть, впрочем, что даже если бы там и находились другие переменные, это не было бы для нашего диверсанта препятствием — ему достаточно просто передать более длинный блок данных.
Переполнение массива arg приведет к нарушению заголовка стекового кадра. Если диверсант достаточно квалифицирован, он может передать
нам вместо команды кусок кода и поддельный стековый кадр, который в качестве адреса возврата содержит адрес переданного кода (конечно, для этого надо точно знать, где у нашей программы находится стек, но это часто одно и то же место). И тогда, при попытке возвратить управление, наша программа передаст управление на подставленный ей код (рис. 12.22). Количество гадостей, которые этот код может содержать, превосходит всякое воображение.

Рис. 12.22. Срыв стека с передачей троянского кода

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

Примечание
Обычно эти термины применяются для описания приемов, которые используются диверсантами для причинения ущерба системам", но важно понимать, что атаки такого типа основаны на ошибке в коде атакуемой системы. Если бы ошибки не было, диверсант не был бы в состоянии что-либо сделать (или, во всяком случае, был бы не в состоянии сделать именно это).

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

fscanf(socket, "%s %s\n", cmd, args);

нам следует написать

fscanf(socket, "%4s %255s\n", cmd, args);

Однако автоматизировать проверку того, что в каждом случае все форматные спецификаторы указаны правильно, невозможно, и поэтому использовать процедуру fscanf и другие процедуры того же семейства не рекомендуется.

Распространение червя Морриса через срыв буфера
Широко известен срыв буфера в программе fingerd, входившей в систему BSD Unix. На процессорах VAX и MC68000 отсутствует защита страниц памяти от исполнения, поэтому любая страница памяти, доступная для чтения, может быть исполнена.
"Червь Морриса" [КомпьютерПресс 1991] пользовался этой дырой, передавая кусок кода и поддельный стековый кадр, передававший управление этому коду. Код в свою очередь запускал на целевой системе копию командного интерпретатора, исполнявшуюся с привилегиями суперпользователя. Затем червь использовал полученный командный интерпретатор для втягивания в систему своего тела.
Ошибка была обнаружена в 1987 г. и вскоре после обнаружения была исправлена. Практически все современные системы используют безопасную в этом отношении версию fingerd. С тех пор сколько-нибудь серьезных (т. е. — вышедших за пределы одной группы взаимно доверяющих машин) атак червей на Unix-системы не происходило.
Червь Code Red, пандемия которого произошла в августе 2001 г., использовал срывы буфера в IIS (флагманский сетевой продукт Microsoft, сервер FTP/HTTP и ряда других протоколов для Windows NT/2000/XP). Как выяснилось, в данном случае речь шла не об одной, а о целой группе ошибок, потому что за выпуском patch, защищавшего от Code Red, последовало несколько других атак червей и поливалентных (т. е. использующих несколько каналов размножения) вирусов, часть из которых также привела к пандемиям. 19 сентября 2001 г. аналитическая компания Gartner Group выпустила доклад [www3.gartner.com 101034], в котором настоятельно рекомендовалось как можно скорее отказаться от использования IIS и высказывалась крайне пессимистическая оценка способности Microsoft исправить положение в обозримом будущем.

Срывы буфера являются одним из наиболее распространенных уязвимых мест: так, в базе данных [www.cert.orgl они составляют 27% от общего количества документированных проблем.
При использовании других языков программирования, например C++ с библиотекой классов для работы со строками, или Java, реализовать программу, подверженную срыву буфера, несколько сложнее, однако возможности человеческие неисчерпаемы, и многим программистам это удается. Впрочем, для программирующих на Java есть одно утешение: Java Virtual Machine использует более сложную схему управления памятью, чем компилируемые алголоподобные языки, и разрушить стековый кадр посредством переполнения буфера в программах, написанных на Java, невозможно, поэтому данный прием не может применяться для передачи и исполнения вредоносного кода. Однако неправильно обработанное исключение при ошибке индексации в буфере может привести к аварийной остановке приложения Java с ничуть не меньшим успехом, чем ошибка доступа к памяти в C/C++.
В тесном концептуальном родстве со срывами буфера находятся ошибки, срабатывающие при использовании во входном потоке данных недопустимых величин смещения (рис. 12.23). Такие ошибки встречаются при анализе входного потока, который содержит взаимосвязанные структуры данных, связи между которыми реализованы в виде смешений в потоке (я ссылаюсь на структуру данных, которая последует через 50 байт после этой точки). Практически важный пример такого протокола — система квитирования (посылки подтверждений) со скользящим окном, используемая в транспортном протоколе TCP [RFC 0793]. Адресация посредством смещений широко применяется также при работе с последовательными файлами, поэтому драйверы файловых систем и сетевые файловые серверы также могут содержать такие ошибки.

Рис. 12.23. Использование недопустимых смещений

Задание смещений, превосходящих размер буфера анализирующей программы, или недопустимых по каким-либо другим правилам — например, отрицательных, если по протоколу допустимы только положительные -может приводить к формированию указателей за пределы анализируемого буфера. Модификация данных по этим указателям может приводить к разнообразным последствиям — например, таким способом можно попытаться убедить файловый сервер, что файл, открытый для чтения, в действительности открыт для записи. Даже если в пределах досягаемости сформированного таким образом указателя и нет критически важных данных, практически всегда его можно использовать для разрушения целостности переменных состояния атакованного модуля и осуществления DoS.
В многопоточных сервисах распространены также ошибки соревнования. Для их срабатывания необходима определенная последовательность и временное согласование запросов к сервису.
В некоторых типах сервисов встречаются свойственные им ошибки. Так, во многих серверах HTTP была обнаружена ошибка подъема по каталогам (directory traversal bug), когда злоумышленник, запрашивая URI, содержащие последовательности '..', мог подняться по файловой системе выше корневого каталога HTTP-сервера и, таким образом, считать или даже модифицировать файлы, не входящие в иерархию HTML-документов (рис. 12.24). Аналогичные ошибки встречаются и в сетевых файловых серверах.

Рис. 12.24. Ошибка подъема по каталогам

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


Практические рекомендации

  ЯСНОСТЬ МЫСЛИ. РЕАЛИСТИЧНЫЙ ПОДХОД ЧТО ОЧЕНЬ ВАЖНО ДЛЯ РАБОТЫ. ПОДОБНОЙ НАШЕЙ. Т. Пратчетт

Некоторые из приводимых рекомендаций уже упоминались в тексте, но здесь мы постараемся собрать их воедино.
Пользователь не должен иметь доступа к данным более того, что требуется для исполнения им служебных обязанностей. Это позволяет минимизировать эффект исполняемых пользователями троянских программ и прямых проникновений в систему от имени этого пользователя, а также вред, который пользователь может причинить сам, как сознательно, так и по ошибке. Кроме того, работа с ограниченным подмножеством данных удобнее для пользователя и иногда приводит к повышению производительности.
Когда это возможно, доступ к разделяемым данным следует устанавливать не индивидуальным пользователям, а группам. Список групп и структура их вложенности должны соответствовать иерархической структуре организации и существующим в ней функциональным группам должностей. Многие современные ОС поддерживают иерархические структуры учетных записей — как правило, эта иерархия должна соответствовать структуре организации.
Умопостижимая и хорошо и внятно документированная организационная структура оказывает администратору значительную помощь в проектировании структуры групп и ACL, а хорошая документация бизнес-процесса необходима разработчику приложений поддержки бизнеса, в том числе и для проектирования модели безопасности.
Везде, где это не приводит к чрезмерным накладным расходам, следует применять шифрованные протоколы передачи данных. Данные, хранящиеся на компьютерах за пределами здания компании, а особенно на домашних и переносных компьютерах, следует шифровать в обязательном порядке.
Защита данных практически не имеет смысла без защиты самой системы и прикладного программного обеспечения: если злоумышленник имеет возможность модифицировать код системы или прикладной программы, он может встроить в него троянские подпрограммы, осуществляюшие несанкционированный доступ к данным.
Доступ к коду приложений и системы для модификации должен предоставляться только техническому персоналу, занимающемуся поддержкой и установкой обновлений этих приложений. Это позволяет защититься не только от запускаемых пользователями троянских программ (особенно вирусных), но и от ошибочных действий пользователей.
Доступ к конфигурации ОС и прикладных программ также должен требовать высоких привилегий. В идеале, пользователю следует иметь доступ только к настройкам пользовательского интерфейса ОС и приложений.
Все ресурсы системы, которые могут резервироваться пользователями, должны квотироваться. Каждый неквотируемый общедоступный ресурс является потенциальной точкой DoS.
Каждый активный серверный или сервисный процесс, исполняемый в системе, может содержать ошибки и, таким образом, является потенциальной
точкой атаки. Следовательно, все сервисы, которые не нужны непосредственно для работы системы или реально используемых прикладных программ, необходимо остановить. Это может также привести к некоторому повышению производительности.
Поставщики ОС и приложений нисколько не заинтересованы в том, чтобы в их продуктах существовали известные ошибки, особенно же — способные привести к проблемам с безопасностью. Поэтому все сколько-нибудь приличные поставщики ПО как свободно распространяемого, так и коммерческого, публикуют обновления к своим продуктам, patchs (patch — заплата), содержащие исправления обнаруженных ошибок и рекомендации по обходу ошибок известных, но еще не исправленных. Системный администратор должен следить за этими публикациями — что, впрочем, не следует понимать как рекомендацию немедленно устанавливать на промышленно эксплуатируемые серверы самые последние patchs.
При принятии решения об эксплуатации той или иной программной системы — операционной, прикладной или среды разработки — необходимо ознакомиться с политикой поддержки, которую предоставляет ее поставщик.
Во всех случаях когда это возможно, следует делать операционную среду гетерогенной — различные ОС и приложения имеют различные (и, как правило, непересекающиеся) наборы проблем с безопасностью, поэтому сложность взлома гетерогенной среды резко возрастает.
Важным источником информации об известных проблемах с безопасностью (как ошибках в коде ОС и приложений, так и распространенных ошибках при установлении прав администратором) являются списки рассылки и Web-сайты [www.cert.org], [www.ntbugtraq.com] и ряд других, а также специальные списки рассылки, поддерживаемые поставщиками ПО. Хотя антивирусные пакеты и не являются адекватным средством защиты вашей сети от троянских программ, их применением не следует пренебрегать, особенно в средах, где активно используются приложения и ОС фирмы Microsoft. Лучше иметь хоть какую-то защиту, чем вообще никакой. В качестве дополнительного эшелона защиты антивирусный пакет также может оказаться полезен.