ПРИЕМЫ ПРОФЕССИОНАЛЬНОЙ РАБОТЫ В UNIX

ГЛАВА 9

АДМИНИСТРИРОВАНИЕ И БЕЗОПАСНОСТЬ

СОДЕРЖАНИЕ


АДМИНИСТРИРОВАНИЕ И БЕЗОПАСНОСТЬ

ЗАЧЕМ НАМ ИЗУЧАТЬ АДМИНИСТРИРОВАНИЕ

Вашу карьеру в системе UNIX в качестве ученика (стать бы поскорее мастером!) можно представить себе в виде трех ступеней квалификации. Первая ступень - посвящение в работу системы UNIX в целом, особенно изучение ее сердцевины - файловой системы. Первые три главы заложили этот фундамент и предоставили практические инструментальные средства для обслуживания системы. Вторая ступень мастерства - поддержка вашей собственной работы и персональной среды - рассматривается в главах с четвертой по шестую. В главах 7 и 8 более подробно рассматриваются два специальных аспекта практической работы с системой UNIX - устройства и коммуникации.
Теперь мы готовы достичь третьей ступени мастерства - курировать работу самой системы, что более прозаически называется системным администрированием.
Если вы в настоящий момент такой пользователь, который занимается программированием, или если вы все время работаете системным программистом, то вас может удивить, зачем вам становиться на точку зрения системного администратора и овладевать его основными инструментами работы. На это имеется две серьезные причины: знание и необходимость.
Системное администрирование требует близкого знакомства с тем, где и что находится в системе, и понимания взаимосвязи конкретного процесса с системой в целом. Программисты стремятся нахвататься сведений о чудесах и результатах таинственных команд и о всяческих хитростях, которые они считают полезными, но зачастую они не хотят тратить время на знакомство с системой UNIX в целом. Мы бы хотели сагитировать вас на более систематическое изучение системы UNIX с той целью, чтобы вы могли открыть для себя новые кладовые знаний. Вот почему на протяжении данной книги мы создавали инструментальные средства, которые не только делают полезные вещи, но и помогают вам изучать саму систему.
Необходимость знать администрирование становится ощутимой, когда вы обнаруживаете, что вам вдруг задали работу системного администратора или администратор ушел в отпуск, что пользователи выстроились возле ВАШЕГО стола в ожидании помощи, поскольку вас считают признанным авторитетом. Другой причиной возникновения необходимости может быть то, что вы стали безраздельным хозяином вашей собственной микроЭВМ с системой UNIX и хотите все установить и поддерживать по своему вкусу. Взгляните на такую необходимость администрирования как на возможность накопить обширные и доскональные знания о UNIX, которые могут сослужить вам добрую службу в вашей будничной работе с компьютером.
Быть мастером UNIX - дело чести и технической грамотности. Пытаясь удовлетворить требованиям необходимости, мастера UNIX учатся поспевать за потоком необходимых им знаний. Мастера UNIX не только хорошо играют, но и просчитывают игру на один ход вперед.

НЕКОТОРЫЕ НАБЛЮДЕНИЯ ПОСВЯЩЕННОГО В АДМИНИСТРИРОВАНИЕ

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

АДМИНИСТРАТИВНЫЕ ОБЯЗАННОСТИ

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

ПОДДЕРЖКА РАБОТОСПОСОБНОСТИ СИСТЕМЫ

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

УЛУЧШЕНИЕ СИСТЕМНЫХ ВОЗМОЖНОСТЕЙ

По мере того, как все больше и больше людей эксплуатируют систему, требуется все больше ресурсов, но вы можете также найти способы использования имеющихся ресурсов с большей эффективностью. Разрабатывая способы повышения производительности системы, вы найдете для себя много полезного в инструментальных средствах, представленных в главе 3. В системе UNIX редко хватает принтеров, дисковых устройств, последовательных портов, сетевого оборудования и т.п., но более эффективное применение может помочь решить те же задачи без добавления новых ресурсов.
По всей видимости, наиболее важным ресурсом является время центрального процессора. Посадите тридцать пользователей в системе, рассчитанной на двадцати четырех - и вы сразу почувствуете нехватку процессорного времени. В работу администратора входит поддержка текущих ресурсов, а также планирование роста системы на будущее. Поэтому требуется, чтобы вы знали типичные раскладки использования вашей системы, знали, где могут возникнуть "узкие места", как эффективно распределить имеющиеся ресурсы и какие способы наращивания системы могут быть наиболее эффективными по стоимости. Некоторую полезную информацию можно извлечь путем "статического" инспектирования файловой системы с помощью средств, представленных в главе 2. Более динамичную картину эксплуатации системы вы можете получить, применяя команду ps, чтобы увидеть, какие процессы активны в настоящее время, и применяя команду w (в системе Berkeley), которая выдает статистику загрузки системы и организации очередей.

ПОМОЩЬ ПОЛЬЗОВАТЕЛЯМ

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

БЕЗОПАСНОСТЬ: НУЖЕН СТОРОЖЕВОЙ ПЕС

Администратор ведает всеми вопросами безопасности. Обычно он единственный, кто занимается этой работой. Пользователи не обеспечивают безопасность, потому что они не умеют или не знают, как это сделать. Нарушители безопасности могут атаковать систему многими способами. Они могут занять системные ресурсы, заполняя таблицу процессов или таблицу открытых файлов и распределяя для себя все свободное дисковое пространство и все свободные индексные дескрипторы файлов. Они могут перепутаться с другими пользователями системы или поменять системное время. Они могут повредить файлы данных или исполняемые модули и даже подделать почту. Но при вашей организации системы они чаще всего становятся просто "пользователями-хулиганами". Позже мы рассмотрим более серьезные вещи, чем системное хулиганство - тех пользователей, кто может несанкционированно воспользоваться правами суперпользователя.
Наилучший подход к проблемам безопасности - осознать, что действительно нуждается в защите, а не пытаться стать суперсыщиком. Вы должны особенно заботиться о нуждах системных программистов и других опытных авторитетов в вашей системе. В идеале администратор должен работать ВМЕСТЕ, а не против признанных авторитетов и поддерживать с ними хорошие деловые контакты. Не у всех нарушителей одинаковые мотивы. Например, кто-то из авторитетов может захотеть получить доступ к правам суперпользователя для того, чтобы самостоятельно делать некоторую работу, а не ждать, когда ее сделаете вы. Кто-то другой может быть обижен на кого-то или вообще на весь мир и стремится отомстить путем разрушения файлов. Каждая ситуация требует индивидуальной оценки. Напомним, что разделяющая линия между администраторами и системными авторитетами зачастую неопределенная и непостоянная. Безопасность иногда превращается в игру, в которой определенные пользователи пытаются разглядеть, чего они могут избежать, а администраторы пытаются сохранить контроль над системой.
В работе сторожевого пса задействовано пять функций:
  1. Защита от неразрешенных входов в систему, файлов, программ и команд su.
  2. Сохранение конфиденциальности определенных данных.
  3. Наблюдение за использованием модемов.
  4. Предотвращение неразрешенных пересылок файлов.
  5. Сведение к минимуму возможностей взлома.
Здесь много работы! Система UNIX так обширна, и файлы могут скрываться в таком большом количестве мест, что один лишь поиск самозванцев занимает почти все время. Это требует от администратора не столько тяжелой, сколько изобретательной работы. Для того чтобы обеспечить себе шансы на победу в этой борьбе, вы должны сделать так, чтобы система помогала себя защищать. Несколько позднее в этой главе мы предложим инструментальные средства access и suw, которые помогают вам защищаться от запрещенных входов в систему, и командный файл chkset, имеющий дело с защитой конфиденциальных файлов. Мы также предлагаем более детальный взгляд на конкретные проблемы безопасности.

ЗАЩИТА ОТ ЗАПРЕЩЕННЫХ ВХОДОВ В СИСТЕМУ, ФАЙЛОВ, ПРОГРАММ И КОМАНД su

Имеется много способов получения несанкциониованных привилегий в системе UNIX. Самый простой способ - иметь корневой (суперпользовательский) интерпретатор shell. Это такой shell, который запускается как особо привилегированный процесс, имеющий возможность читать, удалять или модифицировать ЛЮБОЙ файл в системе независимо от того, какие права доступа установлены для этого файла его владельцем. Корневой shell можно заполучить, узнав корневой пароль у неосторожного администратора или при помощи других средств, рассматриваемых ниже.
Несанкционированный пользователь, имея доступ к правам суперпользователя, может подготовить "потайные двери", обеспечивающие дальнейший запрещенный доступ. Они позволяют нарушителю запускать shell с корневыми привилегиями. Более подробно мы рассмотрим их позднее.
Потайные двери могут выступать в различном обличье. Они могут быть исполняемыми модулями, латками в системных утилитах или латками в системных файлах. Администратор должен вести постоянное наблюдение за изменениями в системе и уметь противодействовать всяческим вмешательствам. Ниже мы рассмотрим некоторые инструментальные средства и приемы, помогающие вам обнаруживать такое проникновение.

ВХОДЫ В СИСТЕМУ

Начнем с несанкционированных входов в систему. Это может произойти многими способами. Бывает, что нарушитель добавляет свое собственное регистрационное имя в парольный файл и помещает туда свой пароль. Если администратор не знаком с парольным файлом или давно туда не заглядывал, то такую несанкционированную запись можно проглядеть.
Другой метод несанкционированного входа в систему заключается в том, что кто-то может завладеть всеми паролями, вставляя в программу login "латку" с текстом, направлящим все введенные пользователями пароли в потайной файл. Ниже мы рассмотрим некоторые типы таких "латок".
Конечно, такая изысканная работа зачастую совсем не обязательна. Как известно, люди оставляют свои пароли написанными на листках бумаги в незапертых ящиках стола. Для некоторых верхом секретности является применение комбинации первого и последнего имени в качестве пароля. Однако если уж нарушитель знает много паролей, он может применять каждый раз различные регистрационные имена, чтобы не попадаться на опасном имени.
Пробить систему защиты UNIX можно с помощью "исполняемых регистрационных имен". Это имена, которые запускают программу, а не просто предоставляют вам shell, что является обычным способом начала сеанса работы пользователя в системе. Это может выглядеть примерно так:
date::100:50:Print the date:/bin:/bin/date
who::101:50:Print all logged on users:/bin:/bin/who

Это может запустить любой, кто имеет доступ к терминалу или модемному порту. Иногда это правильные имена, например date, who или sync. Хотя для администратора может быть удобным наличие программ, запускаемых при входе в систему, они часто становятся лазейками, через которые кто-нибудь может проникнуть в систему и обнаружить много информации о системе.
Самые крупные лазейки появляются тогда, когда эти регистрационные имена выполняют командные файлы интерпретатора shell. Как только нарушитель получает привилегии суперпользователя (даже если они лишь временные), он может поместить в парольный файл такую запись, которая в момент входа в систему запускает командный файл интерпретатора shell (или может изменить имеющуюся запись с командным файлом). Сами эти командные файлы можно в любой момент изменить так, чтобы они работали по заданию несанкционированного пользователя. Например, в парольном файле может быть такая запись:
break::102:50::/:/usr/bin/break
Такая запись позволила бы кому угодно набрать имя "break" в ответ на регистрационную подсказку, в результате чего выполнился бы файл /usr/ bin/break. Когда break отработает, снова поступает регистрационная подсказка, и в системе появляется новая лазейка. Почему? Потому что командный файл break может содержать команды для редактора, которые отредактировали бы парольный файл и добавили несанкционированные записи. Это становится возможным по той причине, что процесс getty (печатающий регистрационную подсказку) запускается процессом init, а владельцем файла init является суперпользователь. Такая привилегия передается командному файлу, так как он запущен в момент регистрации в системе, а программам, запускаемым при входе в систему, обычно требуется суперпользовательский доступ для выполнения необходимых инициализаций. В данном случае, однако, он позволяет редактору читать файл /etc/passwd и писать в него. Таким образом, как только нарушитель ОДИН РАЗ получает доступ на запись в /etc/passwd (аналогично "диверсионным программам"), он может установить постоянный доступ, часто даже через несколько точек входа.
И еще. В старых версиях UNIX попадаются некоторые ошибки, предоставляющие суперпользовательские возможности. Например, если в пользовательской записи парольного файла не указан номер пользовательского идентификатора, то по умолчанию он считается нулевым, т.е. суперпользовательским. В эту лазейку очень легко проникнуть. Пример такой записи:
rt::::The Super User:/:/bin/sh
Вот некоторые другие проблемы, за которыми должен следить администратор. Если первая строка парольного файла пустая, то пользователь может зарегистрироваться как корневой без пароля. Проверьте также запись "bin" в парольном файле, которая обычно запускает системные программы. Если запись bin не содержит пароля, как в приведенном выше примере, кто-то может войти в систему в качестве bin и отредактировать файл crontab, чтобы применить к парольному файлу команду chmod (change permission mode, изменение прав доступа) и обеспечить себе доступ к нему. Пользователь bin может также отредактировать файл /etc /rc, чтобы сменить парольный файл. Файл rc используется для конфигурирования системы в момент ее старта путем автоматического запуска ряда программ. Все, что нужно для успешного вторжения,- подождать, когда администратор перегрузит систему (поскольку именно в этот момент файл запускается). После перезагрузки нарушитель может войти в систему как обычный пользователь, отредактировать парольный файл, записать его, а потом в любой момент входить в систему в качестве суперпользователя. Это всего лишь несколько способов, которыми можно добиться несанкционированного входа в систему. К сожалению, каждый день выдумывают новые способы.

ФАЙЛЫ И ПРОГРАММЫ

Еще одна сфера злоупотреблений связана с несанкционированным проникновением в файлы и программы. Самый трудный этап для того, кто хочет взломать защиту системы UNIX,- стать суперпользователем первый раз, но как только эта цель достигнута какими-либо средствами, файлыинтервенты можно поместить в любом месте системы. Вторжение может включать в себя размещение "потайных дверей", латание команды login с целью овладения паролями, чтение и изменение системных учетных файлов и т.д. Ниже мы рассмотрим примеры этих и других методов.
Основными файлами, в которые вторгается корневой нарушитель, являются /etc/passwd, /etc/*rc*, /usr/lib/crontab, /usr/lib/uucp/L.sys. Для обнаружения трещин в вашей административной броне можно поискать файлы, для которых взведен бит разрешения установки пользовательского идентификатора (что указывается буквой "s" в правах доступа, отображаемых командой "ls -l"), и файлы, владельцем которых является суперпользователь. Назначение бита установки пользовательского идентификатора - разрешить программе иметь временный доступ к более привилегированному состоянию (например, суперпользовательскому), чем она имеет в момент своего запуска. На самом деле это очень полезное свойство системы UNIX, так как оно позволяет управлять доступом ко многим таким особенностям, к которым вы бы не хотели предоставить непосредственный доступ для других пользователей. К сожалению, в эти программы может кто-нибудь проникнуть, чтобы использовать их временный корневой статус для вредительства, которое мы уже описывали. Таких файлов имеется конечное число, и все они могут быть проверены. Рассматриваемый далее командный файл chkset автоматизирует для вас процесс проверки. Тем не менее, знание того, какие файлы МОГЛИ быть подвергнуты вмешательству, еще ничего не говорит о том, в какие файлы ДЕЙСТВИТЕЛЬНО произошло вторжение и как. Тяжелее всего обнаружить залатанные системные файлы. Некоторыми из часто латаемых файлов являются login, su, passwd, ps, crypt и mv.
Бывает, что изощренный нарушитель скрывает даты модификации файла, чтобы никто не смог его обнаружить по этому признаку. Единственный способ зафиксировать такое вмешательство - иметь КОНТРОЛЬНУЮ СУМ- МУ, т.е. запись с суммой (количеством байтов) всех важных файлов и хранить ее в отдельном месте или в закодированном виде. Путем периодической сверки старых сумм с новыми, можно обнаружить измененные файлы.
Еще одна вещь, за которой должен следить администратор, это "скрытые файлы". Скрытые файлы являются частью системы и имеют определенный смысл: они предназначены для того, чтобы не загромождать распечатки каталогов. Для того чтобы скрыть файл, нужно сделать первым символом имени файла точку (.). При использовании команды ls вы должны указать опцию -a, если вы хотите увидеть файлы, начинающиеся с точки. Обнаружение запрещенных файлов может быть затруднено, если файл зарыт на три-четыре уровня каталога вниз и назван незаметным именем. Решение заключается в том, чтобы всегда применять опцию -a команды ls, если вы сталкиваетесь с проблемами. Некоторые команды по умолчанию печатают файлы, начинающиеся с точки. Ncheck(1M) печатает все файлы, имеющие взведенный бит разрешения установки пользовательского идентификатора. Если файл назван странным образом, его сразу же видно. Одним из моих любимых является файл "...". Он выглядит несколько странно, но это правильное имя файла. Вы даже можете завести имя файла, образованное 14 точками - такова максимальная длина имени файла.

КОМАНДЫ su

Последний вопрос, за которым нужно следить,- запрещенные команды su. Su - это такое средство, которое позволяет вам ПОДСТАВИТЬ другой пользовательский идентификатор вместо вашего собственного. Если кто-то знает корневой пароль, он может войти в систему с любого терминала и применить команду su с корневым паролем. Однако, это, вероятно, тот случай, когда нарушители потратят больше всего времени, пытаясь чего-либо добиться. Дело в том, что все транзакции su записываются в протокольный файл под названием sulog. Правда, к сожалению, если уж нарушитель стал суперпользователем, то ему ничто не мешает модифицировать протокольный файл с целью удаления компрометирующих записей. К тому же если редактор vi вызван без имени файла, то никто не может увидеть, какой файл редактируется в то время, когда в системе происходит вредительство.
Но бдительный системный администратор может бороться с этим при помощи команды ps. Она печатает строку о команде su точно так же, как она делает это для всех остальных процессов, поэтому можно сразу же заметить, что кто-то превратился в суперпользователя командой su. Нарушителя выдает то, что родительский процесс имеет регистрационное имя, а владельцем su является суперпользователь. Наконец, все равно же нужен корневой пароль. А если кто-то уже знает корневой пароль, то зачем ему связываться с командой su? Применять su было бы резонно только в том случае, если бы залатать команду su так, чтобы она не записывала транзакцию в протокол и изменяла строку, которую печатает ps. Мы еще не знаем, чтобы кто-нибудь добился такого эффекта.

СОХРАНЕНИЕ КОНФИДЕНЦИАЛЬНОСТИ ДАННЫХ

Даже если допустить, что секретность обеспечена, бывают случаи, когда администратору нужно защитить важные файлы от любопытных глаз. В системе UNIX это можно сделать с помощью специальных атрибутов защиты файла, специальных групповых прав доступа, шифровки или даже размещения этих данных на диске, который монтируется только в случае необходимости. Однако, такие данные не должны оставаться физически присутствующими в системе, если они не монтированы, потому что нарушитель может их смонтировать и получить к ним доступ. Командный файл mntlook, рассмотренный ранее, умеет просматривать все устройства и находить такие доступные, но немонтированные файловые системы.
Необходимо соблюдать такое правило: "Если вы не хотите, чтобы кто-нибудь видел этот файл, не держите его на виду". И не думайте, что вы так хорошо его спрятали, что никто не сможет его найти. Если люди имеют суперпользовательский доступ в вашу систему, они могут за считанные минуты получить распечатку каждого файла этой системы. Затем, когда вы не видите, они могут при помощи uucp передать интересный файл в другую систему для последующего изучения, скопировать его на гибкий диск или даже отпечатать. Помните, что если в вашу систему проник несанкционированный пользователь, НИКАКОЙ БЕЗОПАСНОСТИ БОЛЬШЕ НЕТ!

КОНТРОЛЬ ЗА ИСПОЛЬЗОВАНИЕМ МОДЕМА

Модемы являются одной из крупных пробоин в защите системы. Если только у вас нет специальной аппаратуры для предварительной фильтрации обращений в систему UNIX, то она всегда уязвима посредством модемных портов.
Большие вычислительные системы могут иметь произвольное число модемов, как принимающих, так и передающих. Вам может показаться, что поскольку команда login имеет дополнительный пароль для линий с набором номера, то все секретно, но это не так. Имеются программы, которые могут пробовать много комбинаций вероятных регистрационных имен и паролей, и в случае подходящей комбинации команда login может впустить нарушителя в систему!
Обращение вовне, в другие системы через модемы - отдельная история. Обычно тот, кто правильно зарегистрировался в системе, хочет обращаться к другим системам. Но что, если на вашей стороне имеются улавливающие регистрационные имена типа class, education, test и т.д.? Кто-то может войти в систему под видом одного из таких пользователей и использовать модем безо всякого риска быть схваченным за руку. Единственный способ поймать таких нарушителей - по номеру терминальной линии, если у вас имеются специально выделенные линии.
Что произошло бы, если бы тот, кто вошел в вашу систему через модем при помощи одного из перечисленных регистрационных имен, обратился бы потом вовне, к какой-нибудь "дальней земле"? Тогда не было бы никакой возможности уследить за обратным вызовом определенного пользователя.

ПРЕДОТВРАЩЕНИЕ ЗАПРЕЩЕННЫХ ПЕРЕСЫЛОК ФАЙЛОВ

Запрещенные пересылки файлов имеют отношение почти исключительно к средствам uucp. В системе Berkeley (BSD 4.1 и старше) сетевые команды также имеют аналогичные проблемы. Вот пример: если кто-то запускает в системе Berkeley командный файл для "взлома двери", то команда удаленной регистрации в системе (rlogin) регистрирует нарушителя на другой машине в качестве суперпользователя и никогда не спрашивает корневой пароль. Разве это не очевидная пробоина в системе? Несанкционированный пользователь может также применить удаленное копирование (rcp), чтобы скопировать программу "взлома двери" во все системы.
Самое главное следить за протокольными файлами. Но опять же, что если нарушитель удаляет из протокольных файлов все записи, связанные с заданием вопросов? У вас нет способа узнать о том, что это произошло. Еще нужно следить за таким поведением нарушителей, когда они делают вызов и выдают себя за корректную удаленную систему. Они могут добиться этого, изменив узловое имя своей системы таким образом, чтобы оно соответствовало одному их ваших разрешенных "корреспондентов". Изощренного нарушителя очень трудно поймать, но мы предлагаем некоторые идеи, которые должны вам в этом помочь.

СВЕДЕНИЕ К МИНИМУМУ ВОЗМОЖНОСТЕЙ ВЗЛОМА

Это то, чем администраторы часто пренебрегают. Совет номер один - НИКОГДА не оставлять без присмотра терминал, зарегистрированный как суперпользовательский. Бросить без присмотра терминал с корневым доступом - все равно, что оставить тысячу ключей от сейфа компании на вашем столе. Все несанкционированные пользователи могут воспользоваться этим, подготовив командный файл "взлома двери", ожидающий такого момента. Как только они получают в свои руки ваш терминал, всего лишь одна команда предоставляет им безграничные суперпользовательские возможности. С этого момента система перестает быть защищенной.
Системные администраторы должны проверять свои системы и смотреть на них с точки зрения нарушителя. Есть ли хоть когда-нибудь момент, в который система уязвима? Что может произойти среди ночи, когда работают программы резервного копирования? Может ли кто-нибудь завладеть консольным терминалом? Не сможет ли навредить тот, кто приходит к вам помогать? Если вы на секундочку вышли, не сможет ли кто-то применить команду chmod, а потом заполнить экран чем-нибудь другим, чтобы вы не узнали, что это было сделано? Вот те опасности, о которых вам нужно помнить.

ТИПИЧНЫЕ ПРОБЛЕМЫ БЕЗОПАСНОСТИ

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

ПОТАЙНЫЕ ДВЕРИ

Мы уже отмечали, что люди, которые могут получить суперпользовательский доступ в систему хотя бы на короткое время, могут написать программы, предоставляющие им постоянный суперпользовательский доступ. Напомним, что тот, кто хочет прорвать защиту системы UNIX, первым делом пытается найти способ стать суперпользователем. Как мы уже обсуждали, нарушение физической защиты или плохо оберегаемый корневой пароль могут дать нарушителю возможность запустить процесс как суперпользовательский, что предоставляет доступ к файлам (например, стандартным исполняемым модулям системы UNIX), которые не может изменить обычный пользователь. В результате нарушитель получает для себя "потайную дверь".
Ключевым вопросом является способ хранения в системе UNIX указаний о владельце и привилегиях, связанных с файлом. Помимо хорошо известных прав доступа для владельца, группы и прочих пользователей (эти права устанавливаются командой chmod), имеется два более старших бита, называемых setuid (установка пользовательского идентификатора) и setgid (установка группового идентификатора).
Как правило, процесс, запущенный данным пользователем, имеет только те привилегии на доступ, которые принадлежат этому пользователю. Однако, многие системные команды должны иметь доступ к таким файлам, к которым мы бы не хотели разрешать доступ пользователя, за исключением очень ограниченного набора ситуаций. Ярким примером является команда passwd, позволяющая пользователю сменить свой пароль. Очевидно, что этой команде необходим доступ на запись в файл /etc/passwd, а такой доступ имеет обычно только суперпользователь.
Проблему решает исполняемый файл команды passwd, в котором бит setuid установлен на владельца файла, а владельцем файлов, соответствующих обычным системным командам, является суперпользователь (пользовательский идентификатор 0). Это означает, что ВО ВРЕМЯ РАБОТЫ ПРО- ЦЕССА, соответствующего данной команде, пользователь имеет корневые привилегии! Когда команда завершается, прекращается и корневой доступ... если только в данную команду не было какого-то вмешательства или если нарушитель не установил особую программу setuid. В этих случаях остается только войти в потайную дверь.
Потайная дверь - это чаще всего файл, владельцем которого является суперпользователь, но который подвергнут вмешательству несанкционированного пользователя, завладевшего каким-то образом правом доступа на запись в этот файл, обычно путем временного суперпользовательского доступа. Важно понимать, что потайная дверь - это просто еще один процесс, порожденный из обычного пользовательского интерпретатора shell, но с одной существенной особенностью: у него другой номер пользовательского идентификатора - как правило, 0, т.е. идентификатор суперпользователя. Поскольку пользовательский идентификатор хранится в самом процессе, он может быть подвергнут вмешательству.
Фактическое проникновение в систему с обретением возможностей суперпользователя происходит тогда, когда работает "дверная" программа. Здесь используется волшебство бита setuid. Когда этот бит взведен, программа устанавливает (или изменяет) пользовательский идентификатор процесса на пользовательский идентификатор владельца данного файла (который оказывается суперпользовательским). Пока этот пользовательский идентификатор временно является суперпользовательским, программа превращается в shell-интерпретатор (обычно путем выполнения системного вызова exec). Такой shell находится по другую сторону двери, в царстве суперпользователя, со всеми принадлежащими ему привилегиями.
Как мы уже отмечали, обсуждая команды su, более изощренные нарушители могут различными способами маскировать свое прониконвение в систему. Один из способ маскировки - иметь "дверную" программу, которая ничего не делает, если только она не вызвана с какой-нибудь незаметной опцией, например -z. Скорее всего, программа потайной двери не выдает сколько-нибудь полезного синтаксического сообщения, если ее вызвать без правильной опции.
Еще одна хитрость заключается в том, что программа потайной двери может изменить свою командную строку (которую можно отобразить при помощи команды "ps -ef", выдающей полное состояние процесса) на какую-нибудь безобидную, запускаемую обычно суперпользователем (например, getty).
Опытный нарушитель вряд ли оставит исходный текст программы потайной двери в системе, поэтому администратор вынужден разглядывать только исполняемый модуль. Для реассемблирования объектного кода можно применить отладчик (adb), но если только вы не имеете безумно близкого знакомства с внутренностями системы UNIX, вам будет весьма трудно представить себе, что происходит. Изощренные программы потайной двери избегают также присутствия легко узнаваемых строк в исполняемых модулях. Вы можете, однако, применить команду strings (если она есть в вашей системе) для поиска символьных строк, которые там могли бы быть.

ПРОТОКОЛЬНЫЕ ФАЙЛЫ

Одна из простейших ловушек для того, кто пытается добыть права суперпользователя - создавать запись, помещаемую в протокольный файл. При этом администраторам нужно следить за протокольными файлами, не появляются ли там записи, которые могут быть признаком злодейства. Ниже мы покажем вам инструментальное средство, которое автоматически следит за одним из таких протокольных файлов - файлом sulog, содержащим транзакции "замененного пользователя". Другой протокольный файл, часто нуждающийся в проверке, это протокол программы uucp, потому что эта программа может быть использована для несанкционированных пересылок файлов. Многие нарушители пытаются проверить протокольные файлы и удалить компрометирующие записи, сгенерированные при их вмешательстве. В арсенале администратора есть средства борьбы с этим. Они не на 100 процентов эффективны, но отлавливают некоторых нарушителей и, усложняя им жизнь, могут отбить охоту вторгаться в систему.
В дополнение к обычным протокольным файлам, поддерживаемым системой UNIX, некоторые администраторы заводят свои собственные протокольные файлы, а затем подправляют ключевые команды так, чтобы они помещали данные в эти новые регистрационные файлы в процессе своей работы. Это может помочь обезвредить неосторожных лазутчиков. Один знакомый администратор сделал протокольный файл для команды cu и назвал его /tmp/.../.culog. Довольно умный тайный фокус, но в /usr/lib/crontab у него была запись для периодической печати этого файла. Это его выдавало: нужно было маскироваться получше. Заметим также, что ваши "скрытые" имена протокольных файлов могут быть извлечены путем просмотра исполняемого образа команды с помощью утилиты strings.
Если у вас есть пользователь, от которого вы ожидаете чего-нибудь запрещенного, вы должны уметь установить специальную систему регистрации, которая запускала бы более совершенный механизм, когда такой пользователь работает в системе. Программу watch из главы 6 можно модифицировать так, чтобы она вызывала специальную протоколирующую программу, когда в систему входит пользователь из известного списка. Протоколирующая программа могла бы повторять команды ps (process status, состояние процесса) и/или делать "моментальные снимки" обычных регистрационных файлов (особенно учетных файлов) и направлять результаты в припрятанный протокольный файл. Идея состоит в том, что опасные процессы можно было бы обнаружить до того, как нарушитель получает возможность войти в протокольные файлы и изменить их. (Видимо, вам нужно избегать применения команды at в такой программе, а периодически пользоваться вместо нее командой sleep. В противном случае, нарушитель может распознать ваши мероприятия по записи файла crontab.) Как только вы имеете результат о сеансе работы опасного пользователя, вы можете запустить grep для поиска интересующих вас имен или написать инструментальное средство, которое выполняет для вас такой поиск.

УЧЕТНЫЕ ФАЙЛЫ

Вероятно, наиболее важным среди протокольных файлов является учетный файл. В учетном файле имеется запись о каждом и всяком процессе, запускаемом в системе. Точную структуру можно посмотреть в файле /usr/include/sys/acct.h. В одном из полей этой структуры записаны процессы, имеющие суперпользовательские возможности.
Когда кто-либо входит в систему через корневую дверь, для shellинтерпретатора, который он запускает, и для всех процессов, которые он порождает, владельцем является корень (суперпользователь). В учетном файле отражен номер терминала, с которого запущен процесс, поэтому вы можете увидеть корневые процессы, запущенные с таких терминалов, на которых пользователям не разрешен суперпользовательский доступ.
Если у вас имеются обычные линии с набором номера, то все такие записи могут представлять не одного и того же пользователя. Другие входы в систему могут иметь одинаковый номер терминала, но разные пользовательские идентификаторы. Однако, вы можете знать, кто обычно имеет доступ к некоторым выделенным линиям.
Учетные файлы могут хорошо разоблачить процессы, имеющие не такой пользовательский идентификатор, как у лица, запустившего эти процессы. Поищите процессы, владельцем которых был известный пользователь, но которые имеют суперпользовательские возможности. Среди них могут быть корректные записи, например lpr, так как отображаются все системные программы, запущенные со взведенным битом setuid. Записи, которые мы ищем, относятся к shell-интерпретаторам с установленным учетным флагом суперпользователя. Это выдает тот факт, что была выполнена программа потайной двери. Изучите подключаемый файл acct.h, чтобы увидеть все определения. Используя бит ASU для проверки поля, мы можем изолировать флаговую область, отражающую привилегию суперпользователя. Самый лучший способ рассмотреть эту структуру - написать программу на языке Си, печатающую все элементы структуры. В следующей распечатке показаны некоторые важные учетные поля:

--------------------------
|
|  cmd   f   uid   tty      btime
|
|  more  0   russ   0   Sat Jul  5 01:25:59 1986
|  ls    0   russ   0   Sat Jul  5 01:31:12 1986
|  ps    0   russ   0   Sat Jul  5 01:31:59 1986
|  id    0   russ   0   Sat Jul  5 01:34:00 1986
|  pwd   0   russ   0   Sat Jul  5 01:34:12 1986
|  sh    1%  russ   0   Sat Jul  5 01:33:51 1986
|   \__ корневой shell с эффективным пользовательским идентификатором
|
|  sync  0   russ   0   Sat Jul  5 01:34:21 1986
|  df    0   russ   0   Sat Jul  5 01:34:27 1986
|  id    0   root   0   Sat Jul  5 01:34:37 1986
|  sh    2#  root   0   Sat Jul  5 01:34:33 1986
|   \__ корневой shell с реальным пользовательским идентификатором,
|       2# обозначает бит суперпользователя,
|       владелец изменен на root
|
Отметим, что shell-интерпретаторы с эффективным пользовательским идентификатором маскируют бит во флаге суперпользователя, но владельцем их процессов является обычный пользователь. Не известно, все ли системы применяют значение 1 в качестве флага shell-интерпретатора с эффективным пользовательским идентификатором. Похоже, что Berkeley поступает именно так, а System V нет.

КОМАНДА su

Как мы уже отмечали, UNIX предоставляет пользователям обычный способ стать суперпользователем - это команда su. Как видно из предыдущего изложения, суть команды su заключается в системном вызове exec. Тот, кто применяет команду su, должен знать корневой пароль, транзакция протоколируется в файле /usr/adm/sulog, а команда ps оглашает тот факт, что активен корневой shell. Этот прием не самый хитроумный.

ДОСТУП К ТЕРМИНАЛУ СУПЕРПОЛЬЗОВАТЕЛЯ

Помните о том, что НИКОГДА нельзя оставлять без присмотра терминал, на котором вы работаете в качестве суперпользователя? Пока вы отсутствуете, кто-то может воспользоваться этим терминалом, чтобы выполнить команду chmod с целью установки бита пользовательского идентификатора. Хорошо подготовленный нарушитель уже имеет откомпилированную программу потайной двери, владельцем которой является суперпользователь, и ждет, когда будут изменены права доступа. Не остаются ли консольные терминалы доступными в качестве суперпользовательских ночью, во время действий по резервному копированию? Если остаются, то наутро администратор может оказаться в незавидном положении!

БОЛЕЕ ПОДРОБНО О ПОЛЬЗОВАТЕЛЕ bin

Мы уже упоминали о "лазейке" в некоторых системах, позволяющих пользователю "bin" без труда завладеть суперпользовательским доступом. Проблема "bin" имеет еще ряд аспектов. Если несанкционированные пользователи могут войти в систему через bin (являющийся владельцем большинства дистрибутивных исполняемых модулей), то они почти наверняка смогут получить права суперпользователя. Прежде всего, в некоторых версиях владельцем всех исполняемых модулей, размещенных в каталогах /bin и /usr/bin, является bin. Это значит, что нарушители могут перезаписать или подправить исполняемые модули своими собственными вариантами, выполняющими некоторые особые действия, например "chmod 4755 door", а затем восстановить на место исходную версию исполняемого модуля.
Еще один способ простого превращения bin в суперпользователя заключается в модификации /etc/rc - файла запуска команд ("run command"). Он запускается каждый раз, когда машина загружается в многопользовательском режиме. Записывая в него "chmod 777 /etc/passwd", нарушитель может превратить парольный файл в обычный пользовательский после того, как машина загрузится.
Последний способ - использовать файл /usr/lib/crontab. Этот путь изменен в последней версии System V. Теперь полное имя этого файла /usr/spool/cron/crontabs/xxx, где xxx - файл crontab для каждого пользователя. В старом варианте владельцем файла /usr/lib/crontab иногда является bin. Кто-нибудь может отредактировать этот файл и поместить в него такие, например, команды:

* * * * *        chmod 777 /etc/passwd
* * * * *        chmod 4755 /tmp/door
* * * * *        /bin/su root -c "chmod 777 /etc/passwd"
Все это срабатывает по той причине, что cron выполняется процессом init. Поскольку init - один из первых запущенных процессов, его владельцем является суперпользователь. Поэтому любая команда, которую выполняет cron, имеет корневые привилегии. Звездочки означают, что cron должен выполнить указанные команды в очередной возможный момент времени. Cron запускает процесс, изменяющий права доступа к указанному файлу. Нарушители могут поменять парольный файл (что несколько более опасно) или просто активизировать программу потайной двери. Если две первые команды не сработают, то владелец будет изменен на суперпользователя методом грубой силы - выполнением команды su, а затем передачей команды chmod shell-интерпретатору, запущенному командой su. Вы должны почаще проверять файлы crontab и /etc/rc!

ВОЗМОЖНОСТЬ ЗАПИСИ В СПЕЦИАЛЬНЫЕ ФАЙЛЫ

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

ПЕРЕЗАГРУЗКА СИСТЕМЫ

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

ИСПОЛЬЗОВАНИЕ ПРЕИМУЩЕСТВ ПЕРЕМЕННОЙ $PATH

Кое-кто может воспользоваться ситуацией, когда пользователь имеет каталог $HOME/bin впереди системных каталогов /bin и /usr/bin в своей переменной PATH. Помещая подправленную программу в регистрационный каталог безвредного пользователя, нарушитель заставляет эту программу выполняться вместо настоящей, поскольку система исполняет первый файл, совпадающий с именем команды, который она обнаруживает в ходе просмотра определенного пользователем маршрутного списка. Примером могла бы служить команда ls.
Когда команда выполняется, она запускается с теми же правами доступа, что и запустивший ее пользователь. Конечная цель нарушителей - добиться прав суперпользователя, поскольку тогда они смогли бы выполнить любую команду. Диверсионная программа может подготовить потайную дверь для овладения правами суперпользователя или даже несколько таких дверей. Она может удалить себя, чтобы при очередном вызове данной команды выполнялась настоящая команда. Настоятельная необходимость для администратора - проверять наличие в рабочем пространстве опасных файлов (в частности, исполняемых модулей).

ФАЛЬШИВЫЕ ВЕРСИИ НА ЛЕНТАХ

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

ЗАШИФРОВАННАЯ БАЗА ДАННЫХ

Хотя мы не можем дать гарантию, что кто-нибудь смекалистый не опишет, как расколоть парольную защиту, кодирование пароля в системе UNIX по алгоритму DES считается довольно секретным. (Рассмотрение механизма DES выходит за пределы данной книги.) К этой защите добавляется одна вещь - два символа, генерируемые случайным образом, называемые "солью" (salt) и хранимые в файле /etc/passwd для каждой записи. "Соль" используется для определения того, какой из 4096 вариантов алгоритма DES применяется для кодирования заданного пароля. Нарушитель мог бы захватить пароль, использовать его "соль" и зашифровать список известных паролей. Если бы результат совпадал с пробным паролем, взлом был бы осуществлен.
Нарушителю пришлось бы иметь доступ к некоторой довольно чувствительной методике, чтобы добиться своего. Нелишняя мера, которую может предпринять администратор,- следить за чрезмерным использованием команды crypt (если она есть в вашей системе). Эта команда специально сконструирована так, чтобы занимать много процессорного времени - не настолько много, чтобы причинять неудобства законным пользователям, но достаточно много, чтобы выявить попытки автоматизированного взлома.

ЗАПАДНЯ

Западня работает только на специально выделенных линиях. Когда UNIX ожидает, что кто-то будет входить в систему, она печатает регистрационную строку из файла /etc/gettydefs. Пользователь вводит свое регистрационное имя и пароль и попадает в систему.
Программа западни извлекает из этого выгоду. Она имитирует поведение экрана во время регистрации. Когда пользователь вводит свое имя и пароль, такая программа печатает сообщение "login incorrect" ("неверная регистрация"), а затем запускает настоящую регистрационную программу. Пользователь думает, что он сделал ошибку и повторяет попытку входа в систему, на этот раз успешно. Регистрационное имя и пароль можно куда-нибудь отложить для последующего изучения. Самая лучшая защита администратора от этого - обучение пользователей. Видимо, с помощью регулярной почты или бюллетеней нужно напоминать им, что если им кажется, что они набрали пароль правильно, но получили при этом сообщение "incorrect", то они должны немедленно сменить свой пароль и сообщить об этом происшествии администратору. Бывают случаи, когда пользователь действительно ошибается при вводе пароля, но к большому количеству таких происшествий нужно отнеститсь со всей серьезностью.

КОМАНДА МОНТИРОВАНИЯ

Команда монтирования была создана для того, чтобы позволить присоединять к системе несколько дисковых устройств. Раньше, в эпоху миникомпьютеров единственным видом дисковых устройств были большие накопители, в которые вставлялись большие дисковые пакеты. Они обычно находились в машинном зале, и только администратор монтировал их.
Теперь многие системы имеют гибкие диски. Они гораздо персональнее и намного меньше, чем большие дисковые пакеты. Это уменьшение размера ощутимо воздействует на важность самого объекта. Похоже, что теперь каждый пользователь может иметь дело со своими дисками, и администратору больше нет необходимости заниматься этим. Такой сценарий работы приводит к следующему.
Обычное действие, предпринимаемое в небольших системах для того, чтобы дать пользователям возможность работать с их собственными гибкими дисками,- это установка бита пользовательского идентификатора для файла команды /etc/mount. Таким образом, когда запускается команда монтирования, ее пользовательский идентификатор становится корневым, и она может смонтировать гибкий диск. Команда демонтирования должна быть подготовлена аналогично.
Кто-то может извлечь выгоду из того, что команда mount может получить во время своей работы права суперпользователя. Обычно в небольших системах одна машина открыта для экспериментов несанкционированного пользователя. Он может стать суперпользователем в вашей системе, подготовить программу потайной двери и поместить ее на гибкий диск. Владельцем является суперпользователь, а права доступа 4755. Затем нарушитель может размонтировать гибкий диск и войти в защищенную систему.
С этого момента нарушитель может просто входить в систему как обычный пользователь, без всяких специальных прав доступа и монтировать гибкий диск, на котором имеется программа потайной двери. Когда гибкий диск монтируется, файловая система гибкого диска встраивается в файловую систему жесткого диска, и две системы сливаются в одну. Это означает, что потайная дверь для овладения правами суперпользователя готова для файловой системы на жестком диске.
Когда нарушитель запускает программу потайной двери на гибком диске, происходит то же самое, что происходило бы, если бы эта программа была на жестком диске. Мера предотвращения - контролировать использование команды mount в вашей системе. Доступ к команде mount должен быть ограничен определенным кругом пользователей, она не должна разрешать монтировать файлы с установкой пользовательского идентификатора.

АВТОНОМНЫЙ shell (SASH)

В системах UNIX с гибкими дисками загрузочный диск обычно загружается с гибкого накопителя. Подразумевается, что гибкий диск применяется для подготовки жесткого диска и копирования всех файлов системы UNIX с гибкого диска на жесткий. Но за этим кроется нечто большее.
На самом деле загружаемый гибкий диск - это компактная, переносимая версия системы UNIX. Ядро адаптировано к тому, чтобы размещаться на гибком диске, а не на жестком. Когда вы его загружаете, вы получаете интерпретатор shell и среду точно так же, как при работе с жесткого диска. Вот почему такой shell называется автономным (SASH, standalone shell).
  • Корневая файловая система на гибком диске даже выглядит точно так же, как файловая система жесткого диска. Фактически вы можете смонтировать загружаемый диск и скопировать утилиты с жесткого диска на гибкий. Нужны две важные команды: mount и umount. Ограничением является размер гибкого диска. На него не так много помещается.
    Сценарий, с помощью которого несанкционированный пользователь может применить SASH для входа в систему с суперпользовательскими привилегиями, выглядит примерно так. Сначала он должен отключить питание или перезагрузить защищенную систему. Затем он должен загрузить SASH и смонтировать корневую файловую систему жесткого диска в точку монтирования своей файловой системы гибкого диска. Команды могут быть такими:
    # /etc/mount /dev/fp001 /mnt <-- для System V
    # /etc/mount /dev/hd0a /mnt <-- для XENIX
    Это дает нарушителям доступ на жесткий диск при помощи обращения /mnt/*. Все, что им нужно для редактирования файла /etc/passwd - это пройти вниз по дереву каталогов. Для этого можно применить такие команды:
    # /mnt/bin/vi /mnt/etc/passwd
    # sync
    Теперь жесткий диск изменен, и его можно вернуть на место. Нарушитель может остановить автономный вариант UNIX и перезагрузиться с жесткого диска. Он может использовать новое регистрационное имя, созданное при помощи SASH. Мы не знаем, насколько часто люди могут предпринимать такие попытки. Небольшие системы более уязвимы, но в них и меньше пользователей (и потенциальных злодеев). Во многих случаях нижней границей "логической защиты" становится "физическая защита". Большинство людей, имеющих большие машины или даже мини-ЭВМ, постоянно осознают, что им есть что защищать. А микро-ЭВМ выглядят настолько "дружественными" и простыми, что люди обычно забывают, что информация, которая содержится на микрокомпьютерах, при определенных обстоятельствах может оказаться настолько же желаемой и значительной, как и на больших машинах.

    ПРАВКИ ИСХОДНЫХ ТЕКСТОВ

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

    ЯДРО

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

    ПРОГРАММА passwd

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

    ПРОГРАММА crypt

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

    КОМАНДА su

    Поскольку команда su предоставляет суперпользовательский доступ для обычных пользователей, имеющих корневой пароль, это еще одна потенциальная лазейка в защите системы.
    Общая схема работы команды su выглядит так:
    
    --------------------------------------------
    |
    |  Получить информацию о пользователе: пользовательский идентификатор,
    |  групповой идентификатор, пароль, номер терминала, ...
    |  Если пароль пустой или пользовательский идентификатор равен нулю,
    |      То пройти мимо вопросов о пароле.
    |
    |  Запрос пароля
    |  Если зашифрованный вариант того, что было только что набрано,
    |       не совпадает с парольной строкой из файла /etc/passwd,
    |  То   запротоколировать неудачную попытку применения su,
    |       напечатать сообщение "sorry" (сожаление по поводу неудачи),
    |       выйти.
    |  Пароль прошел:
    |    запротоколировать успешную попытку применения su,
    |    выполнить системные вызовы для того, чтобы ввести в действие
    |      пользовательский и групповой идентификатор,
    |    установить среду, если это требуется,
    |    выдать на консоль сообщение, если это корневой shell,
    |      а вы не за системной консолью,
    |    организовать аргументы для показа su в команде ps,
    |    выполнить интерпретатор shell.
    |
    
    Для подправленной версии потребовались бы лишь небольшие изменения в приведенной выше последовательности. Вместо того, чтобы сразу же зашифровывать пароль, su могла бы проверить "секретный" пароль нарушителя.
    Если введен такой пароль, то проверку пароля и действия по протоколированию можно обойти, поэтому запрещенный доступ не отразился бы в протоколе. Несанкционированный пользователь добился бы того, что ДРУГИЕ пароли для команды su записывались бы в "секретный" файл. В результате он бы потихоньку получил все интересующие его пароли для потенциального использования. Для пользователя команда su срабатывала бы успешно, если пароль правильный, а нарушитель получал бы в свое распоряжение пароль.

    КОМАНДА login

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

    ПРОСТИТЕЛЬНЫЕ ГРЕХИ

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

    СИСТЕМНЫЙ РЕЖИМ

    Данный прием, пожалуй, редко применяется, если только у вас нет человека, который очень близко знаком с низкоуровневым функционированием того или иного процессора, используемого в вашей машине. Он может проникнуть в сердце аппаратного оборудования и пристроиться поверх операционной системы. Тем не менее, администраторы должны осознавать, что такие вещи возможны.
    Во многих процессорах, например в процессоре Motorola 68000, имеется регистр состояния процессора (Processor Status Register), называемый обычно PSW, хотя у разных процессоров он может называться по-разному. PSW содержит бит, определяющий, работает ли машина в "супервизорном" или в пользовательском режиме. Этот режим важен для многопользовательской аппаратуры, поскольку все пользовательские программы работают в пользовательском режиме, что сегментирует и защищает память от "коллизий" между процессами.
    С другой стороны, ядро работает в супервизорном режиме. Это означает, что защита памяти не действует и центральный процессор может изменять содержимое любой ячейки памяти во всей машине. Ядру необходима такая возможность, поскольку ядро поддерживает механизм своппинга для перемещения процесса в защищенную память и из нее, когда процесс выполняется.
    Если нарушители безопасности могут получить в прграмму, работающую в системном режиме, то они получают возможность изменять всю память в системе.
    Последствия могут варьироваться от абсолютного разрушения, например записывания нулей в каждую ячейку памяти, до способности читать и сортировать данные в памяти, включая пароли и другую информацию с очень ограниченным к ней доступом.
    Для того чтобы добиться системного режима, нарушителю необходима возможность сгенерировать и установить новое ядро. Используемый метод зависит от того, есть ли у нарушителя исходный текст программ ядра. Приводимые нами подробности относятся к процессору 68000, но могут быть аналогичными для других процессоров.

    СИСТЕМНЫЙ ВЫЗОВ

    Первый метод - создать "пользовательский" системный вызов. Системные вызовы находятся в исходных файлах с именами вида os/sys?.c. Это примерно 60 системных вызовов, и каждый из них имеет специфический номер. Этот номер определяется таблицей системных входов - таблицей адресов точек входа в системные вызовы. Для добавления нового системного вызова необходимо подготовить его исходный код. Когда ядро перекомпилировано и установлено, можно производить системный вызов из любой программы в системе. Как только такой вызов активизирован, он может перевести машину в системный режим.
    К счастью, не так уж легко для "обычного" пользователя перекомпилировать и переустановить ядро системы. Этот метод, вероятно, требует "внутренней работы". Помогло бы хранение ваших исходных текстов подальше от системы, но если вам нужно иметь системных програмистов, регулярно модифицирующих эти исходные тексты, то все, что в ваших силах - ограничить доступ (и подобрать надежных людей)!

    ПСЕВДОУСТРОЙСТВО

    Второй метод может быть использован теми нарушителями, которые не имеют исходных текстов, но имеют все библиотеки, образующие ядро. Здесь подход несколько другой, но результат тот же.
    В соответствии с той же идеей системного режима, цель заключается в том, чтобы в регистре PSW центрального процессора был установлен привилегированный доступ ("супервизорный" или "системный режим"). Вместо того, чтобы использовать надлежащим образом ядро, этот метод пользуется внешним драйвером, который связывается с ядром. Это выполняется путем создания псевдоустройства. Псевдоустройство подобно настоящему устройству, но его имя не ведет ни к какой физической периферии. Доступ к псевдоустройству осуществляется с помощью всех тех же самых примитивов (открыть, закрыть, читать, писать), но это доступ к логической области, а не к физической.
    Для того чтобы определить псевдоустройство, нужно модифицировать главный файл устройства. В главном файле (который называется /etc/master или /usr/sys/conf/master) имеется таблица всех имен драйверов устройств, связанных с каждым примитивом. Когда создается псевдоустройство, в таблицу драйверов устройств помещается новая запись. В этой таблице содержатся имена всех подпрограмм, поддерживающих примитивы.
    Привилегированного режима можно добиться при помощи открытия псевдоустройства. Системный вызов open передает управление драйверу устройства, т.е. добавленному коду. В момент запуска этого кода машина уже находится в системном режиме, поскольку когда выполнялся вызов open, он был "пойман" системой и передан программе обработки, функционирующей в системном режиме. После этого драйвер устройства может делать то, что он хочет.

    НАРУШИТЕЛЬ ВЫДАЕТ СЕБЯ ЗА УДАЛЕННЫЙ УЗЕЛ uucp

    Если команда login подобна сторожу крепости, то программа uucp подобна заброшенному спасательному туннелю, через который враги могут проникнуть во дворец. С приходом межмашинных коммуникаций возникает целый ряд пробоин в защите системы.
    При помощи uucp несанкционированные пользователи могут попасть в систему, выдав себя за удаленный узел uucp. Это очень легко сделать. Нарушители могут заглянуть в файл /usr/lib/uucp/L.sys в вашей системе и обнаружить, где находятся удаленные системы, путем поиска входов в систему на других машинах. Затем они могут посмотреть в файле /etc/passwd такие входы в систему, которые запускают программы uucico вместо обычного shell-интерпретатора. Если они обнаружат соответствующие пароли, они могут попытаться применить некоторые вероятные пароли или использовать один из методов внесения правок, рассмотренных ранее, с целью перехвата паролей.
    Затем нарушитель может изменить имя узла своей системы на имя узла удаленной системы, чтобы выдать себя не за того, кем он на самом деле является. Он может войти в систему под именем uucp или под специальным регистрационным именем, предназначенным для удаленной машины. Программы uucp передают это узловое имя (которое является поддельным) в вашу систему.
    Нарушители могут перекачать почту, файлы и т.д. из вашей системы на свою машину. Если у вас есть что-нибудь в очереди, ожидающей отправки на законную удаленную машину, нарушители могут сразу там очутиться. Вы можете столкнуться с неприятностями, когда один из ваших операторов законной удаленной системы звонит и спрашивает вас, почему он неделями не получает от вас ни почты, ни программных запросов! Однако, коварный нарушитель мог бы переслать копию украденных файлов обратно к вам и использовать прогрессивные средства для отправки их на законную удаленную машину.

    ПОДДЕЛКА ПОЧТЫ

    Этот прием довольно хорошо известен, но мы включаем его для полноты изложения. Похоже, однако, что он работает не во всех версиях системы UNIX. Он работает в System V, но не работает в XENIX, System III и Berkeley 4.2. Данный метод заключается в изменении пользовательской переменной среды LOGNAME. Поскольку команда mail использует ее, чтобы идентифицировать вас при отправке вам почты, меняется заголовок почты. Обычно это всего лишь мелкая неприятность, но вы должны уведомить об этом пользователей, чтобы они очень внимательно относились к таким сообщениям, которые кажутся несвойственными для их мнимого отправителя.

    СКРЫТЫЕ ИМЕНА ФАЙЛОВ ПРИ РАБОТЕ С РЕДАКТОРОМ vi

    Полезной практикой для обеспечения безопасности является выполнение случайных команд ps. Такая мера более-менее равносильна периодическому патрулированию с целью увидеть, не происходит ли что-нибудь опасное. Необходимо, однако, отметить, что лица, использующие редактор vi для несанкционированной работы, могут замести свои следы, выбирая такое имя редактируемого файла, чтобы оно не появлялось в распечатке команды ps. Самый простой способ, которым они могут это сделать - вызвать vi без указания имени файла. Тем самым vi запускается с пустым файлом. Затем они могут применить команду ex для редактирования нужного им файла. Это убережет имя файла от распечатки командой ps, так как оно не является частью набора аргументов команды vi. Массив аргументов формируется при вызове команды vi, а не после ее запуска.
    Другой способ - использовать маскировку. Нарушители могут переименовать файл, который они хотят редактировать, в ничего не означающее имя, например tmp, а потом использовать имя tmp при вызове редактора vi. В результате в массив аргументов занесется имя tmp. Оно и появится в распечатке команды ps.

    --------------------------------------------------------
    ИМЯ: access
    --------------------------------------------------------

    access

    НАЗНАЧЕНИЕ

    Ищет в парольном файле все регистрационные записи, не имеющие паролей.

    ФОРМАТ ВЫЗОВА

    access

    ПРИМЕР ВЫЗОВА

    access Выдает список всех беспарольных входов в систему

    ТЕКСТ ПРОГРАММЫ

    
    1   :
    2   # @(#) access v1.0  Show all free access logins  Author: Russ Sage
    3
    4   if [ "$#" -gt "0" ]
    5     then  echo "access: too many arguments" >&2
    6           echo "usage: access"              >&2
    7           exit 1
    8   fi
    9
    10  grep '^[^:]*::' /etc/passwd || echo "All logins protected"
    

    ОПИСАНИЕ

    ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ access?

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

    ЧТО ДЕЛАЕТ access?

    Командный файл access использует команду grep с шаблоном поиска, описывающим регистрационную запись, не имеющую пароля. Когда такая запись попадается, она печатается в стандартный вывод. Если указанных записей не найдено, выводится сообщение "All logins protected" ("Все входы в систему защищены").

    ПОЯСНЕНИЯ

    Первое, что делает access (в строках 4-8) - проверяет, правильно ли она была вызвана. Поскольку опций не предусмотрено, в командной строке ничего не должно быть. Если количество аргументов в командной строке больше нуля, то на стандартное устройство регистрации ошибок выдается сообщение об ошибке и командный файл завершается.
    Оператор в строке 10 выполняет поиск в парольном файле. Применяется утилита grep, т.к. мы используем в этой команде выражение. Если бы мы использовали фиксированную строку, более предпочтительной была бы утилита fgrep, потому что она быстрее. Выражение, задающее поиск, означает следующее: начиная с начала строки, найти все символы, отличные от двоеточия, вплоть до обнаружения двух двоеточий подряд. Если вы заглянете в файл /etc/passwd, то увидите, что первое поле представляет собой имя (от начала строки до первого двоеточия). Затем между первым и вторым двоеточием размещается пароль. Если пароль отсутствует, то после первого двоеточия сразу же следует второе - именно это соответствует нашему шаблону поиска. Поиск выполнятся в файле /etc/passwd. Если grep успешно обнаружил хотя бы одну запись, то код возврата нулевой. Если grep ничего не обнаружил, то код возврата единица. Тогда активизируется последняя часть строки 10 и выводится сообщение о том, что все записи о входе в систему защищены.

    ----------------------------------------------------
    ИМЯ: chkset
    ----------------------------------------------------

    chkset

    НАЗНАЧЕНИЕ

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

    ФОРМАТ ВЫЗОВА

    chkset [-l] [dir...]

    ПРИМЕР ВЫЗОВА

    chkset -l

    Вести поиск, начиная с корневого каталога, поскольку каталог не указан. С помощью команды "ls -d" выдать список файлов, для которых установлен в единицу бит разрешения установки идентификатора пользователя либо идентификатора группы. Результат отсортировать по имени файла. (Бит установки пользовательского идентификатора S_ISUID и бит установки группового идентификатора S_ISGID являются атрибутами защиты файла наряду с битами прав доступа на чтение/запись/выполнение и определены в подключаемом файле /sys/stat.h. - Примеч. перев.)

    ТЕКСТ ПРОГРАММЫ

    
    1   :
    2   # @(#) chkset v1.0  Check for set bits on  Author: Russ Sage
    3
    4   FORM="-print"
    5   SORT="sort"
    6
    7   if [ "`echo $1 | cut -c1`" = "-" ]
    8     then  case $1 in
    9           -l)     shift
    10                  FORM="-exec ls -ld {} ;"
    11                      SORT="sort +7";;
    12          *)      echo "usage: chkset [-l][file/dir ...]" >&2
    13                  exit 1;;
    14          esac
    15  fi
    16
    17  if [ "$#" -gt 0 ]
    18    then SRC="$*"
    19    else SRC="/"
    20  fi
    21
    22  find $SRC \( -perm -4000 -o -perm -2000 \) $FORM | $SORT
    

    ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ

    • FORM Команда и опции для листинга
    • SORT Команда и опции для сортировки результата
    • SRC Исходный каталог, от которого нужно начинать поиск

    ОПИСАНИЕ

    ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ chkset?

    Мы уже рассмотрели проблемы безопасности, которые могут возникнуть, когда для исполняемых файлов установлен в единицу бит разрешения установки идентификатора пользователя. Это означает, что они могут запускать интерпретатор shell с корневой или с другой привилегией высокого уровня. С той же целью может быть установлен в единицу бит разрешения установки идентификатора группы. Поэтому системный администратор должен непрерывно разыскивать и проверять все файлы в системе, для которых установлены эти биты, чтобы посмотреть, не используются ли они для несанкционированных целей.
    Не для всех интерпретаторов shell, нарушающих защиту, владельцем является суперпользователь (root). Один пользователь может запустить shell, владельцем которого является другой пользователь, имеющий более высокие привилегии. Это фактически предоставляет пользователю, запустившему shell, все возможности владельца файла.
    Найти shell-интерпретаторы, устанавливающие идентификатор пользователя или группы, бывает легко, а бывает и трудно, в зависимости от их авторства. Легко найти такие, которые:
    1. имеют необычные имена (некоторые нарушители любят выставлять свои достижения напоказ);
    2. содержат в исполняемом файле символьные строки, которые можно прочитать;
    3. размещены в необычном или очевидном каталоге;
    4. не имеют ограничений относительно того, кто может их запустить.
    Для изощренных shell-интерпретаторов характерно следующее:
    1. они имеют имена, похожие на обычные команды системы UNIX;
    2. имеют размеры файлов, которые соответствуют другим файлам, размещенным неподалеку от них;
    3. содержат упрятанные символьные строки, которые не так-то легко прочитать;
    4. имеют, возможно, специальную опцию, запускающую shell, или даже специальный пароль, необходимый для его запуска.
    Самые хулиганские из них являются настоящими командами системы UNIX, переделанными в корневые shell-интерпретаторы, которые затем переустанавливаются вместо первоначальных shell-интерпретаторов. Единственный надежный способ идентифицировать этот последний тип - запустить побайтовое сравнение между вашей дистрибутивной копией команды системы UNIX и той версией, которая присутствует в настоящий момент в вашей системе.
    Конечно, перед тем как вы сможете проверить файлы со включенными битами разрешения установки пользовательского/группового идентификатора, вам нужно найти все такие файлы. В системе UNIX это делают две команды: find(1) и ncheck(1M). Утилита find ищет файлы по нашей точной спецификации и может быть использована для поиска файлов с заданным набором прав доступа, включая биты установки идентификаторов. Ncheck печатает вперемешку специальные файлы и файлы с разрешенной установкой идентификатора пользователя. Это очень большой список, чтение и поиск в нем интересующих нас файлов занимает много времени. Таким образом, полезно создать командный файл, предоставляющий нам всю необходимую информацию и только такую информацию. Chkset использует команду find и ищет только файлы со включенными битами разрешения установки пользовательского/группового идентификатора, так что результат содержит лишь необходимую нам информацию, и этим результатом можно сразу же воспользоваться.

    ЧТО ДЕЛАЕТ chkset?

    Chkset имеет два режима функционирования: один для сканирования всей системы в целом, а другой для сканирования указанных деревьев каталогов. Это хорошее свойство, так как сканирование каждого файла системы занимает очень много времени. Если имеется много больших дисковых устройств, проверка всего содержимого системы может занять целый час. Утилита chkset также очень сильно загружает центральный процессор из-за всех процессов, которые она генерирует. Указывая имена каталогов, вы можете выполнить проверку лишь на определенной области системного дерева. Отметим, однако, что поскольку chkset пользуется командой find, она сканирует не только указанный вами каталог, но и ВСЕ подчиненные каталоги. Заметим также, что chkset обнаруживает ВСЕ файлы с установленными в единицу битами установки пользовательского/группового идентификатора, а не только те, владельцем которых является суперпользователь (root).
    Результат работы chkset можно выдать также двумя способами. Если не применять никакую опцию, то форма выдачи результата определяется командой "find... -print", что означает полные маршрутные имена найденных файлов. Затем эти полные имена сортируются.
    Если применяется опция -l, то для форматирования результата используется команда "ls -ld", порождающая длинный формат листинга. При этом распечатываются полное указание прав доступа, число связей, владелец, размер и имя файла. Этот результат также сортируется по именам.
    Выбирайте тот или иной формат в зависимости от обстоятельств. Если вам нужно проверить большой участок системы и получить список подозрительных файлов, примените листинг по умолчанию (без опций), так как он компактнее и, как мы увидим позднее, занимает значительно меньше процессорного времени. Если вы хотите заняться определенным каталогом и посмотреть на его файлы подробно, воспользуйтесь опцией - l. Она предоставляет больше информации и избавляет от необходимости вручную набирать команды ls для интересующих вас файлов.
    Отметим, что эту команду может запустить кто угодно, а не только администратор, имеющий привилегии суперпользователя. Однако, если она запускается обычным пользователем, то команда find внутри командного файла chkset ограничена теми файлами, к которым пользователь имеет доступ на чтение. Так что вы могли бы предложить более привилегированным пользователям запускать chkset в качестве одной из их личных мер безопасности. Разумеется, если chkset запускается суперпользователем, то ограничения прав доступа к файлам несущественны и можно подвергнуть проверке все файлы.

    ПРИМЕР

    # chkset /bin /usr/bin /lib /usr/lib
    Эта команда вызывает просмотр указанных каталогов. В каталогах типа /usr/lib просматриваются все подчиненные каталоги, что обеспечивает более тщательную проверку.

    ПОЯСНЕНИЯ

    Первым делом chkset инициализирует две переменные - FORM и SORT. Переменная FORM содержит команду для выдачи результата работы команды find, а переменная SORT - команду, определяющую, что нужно сортировать.
    В строке 7 проверяется, является ли первый позиционный параметр опцией. Если да, то оператор case (строки 8-14) смотрит, какая это опция. Если это опция "-l", то подготавливается команда для распечатки результата (это мы обсудим позже). Команда для утилиты sort формируется так, чтобы сортировка шла по полю владельца. Опция убирается из командной строки, потому что все последующие аргументы должны быть каталогами и мы захотим получить к ним доступ с помощью "$#". Если попалась опция, отличная от "-l", то это ошибка, выдается сообщение об ошибке (строка 12), и командный файл завершается.
    Если осталось более нуля аргументов, когда мы попадаем в строку 17, то они проверяются в цикле, чтобы убедиться, что все они являются каталогами. Если это не каталоги, на стандартное устройство регистрации ошибок выдается сообщение об ошибке и командный файл завершается.
    Если имеются параметры (т.е. каталоги), то в строке 18 в переменную SRC заносятся все каталоги. Если же параметров нет, то в переменную SRC заносится значение "/", т.е. корневой каталог, чтобы обеспечить подразумеваемую стартовую точку для поиска.
    Вся работа этого командного файла выполняется фактически в операторе find. Команда find допускает множественное указание каталогов, которые поступают в результате чтения их из командной строки и занесения в переменную SRC.
    После того как мы указали команде find, откуда начинать поиск, мы указываем ей, что нужно искать. В данном случае нас интересуют все файлы, которые имеют включенный бит установки пользовательского либо группового идентификатора. Мы объясняем это команде find путем указания прав доступа, которые требуется искать. Строка "-perm -4000" означает поиск всех файлов, имеющих права доступа со включенным битом установки пользовательского идентификатора и с любыми другими включенными битами. Вы можете понимать эту запись как применение символов-заменителей - 4???. Мы ищем как установку пользовательского идентификатора (-4000), так и установку группового идентификатора (-2000), поэтому две строки прав доступа соединены опцией -o, означающей "or" ("или"). (Более полное описание прав доступа в символической и восьмеричной форме приведено в chmod(1).)
    Следующая задача - добавить строку, хранимую в переменной FORM, в командную строку. Если опция -l не была использована, то в переменной FORM хранится строка "-print", а это значит, что find будет печатать маршрутные имена найденных файлов. Если же -l использовалась, то переменная FORM содержит строку "-exec ls -ld {} ;". Опция -exec - это очень гибкая опция команды find, позволяющая применить любые команды, которые за ней следуют, к каждому найденному файлу. В данном случае эти команды выполняют распечатку в длинном формате (-l), причем для каждого каталога (-d) выводится только его имя (а не содержимое). Именно здесь происходят наибольшие затраты ресурсов центрального процессора, так как для опции -l требуется системный вызов stat. Из-за того, что для каждого файла требуется команда ls, она каждый раз загружается в память и выполняется. Производится также доступ к индексному дескриптору файла на диске. Это приводит к большим накладным расходам.
    Затем весь поток данных пропускается через утилиту sort. На самом деле мы хотим сделать сортировку по восьмому полю (вы можете проверить это, выполнив команду "ls -l" и изучив ее результат). Утилита sort ПРОПУСКАЕТ указанное число полей, начиная с поля 1, являющегося по умолчанию стартовой точкой, поэтому использование записи +7 означает переход к восьмому полю, которым является имя файла.

    АЛЬТЕРНАТИВНЫЙ ПОДХОД

    Для поиска файлов с интересующими нас правами доступа можно применить другой метод, хотя и более медленный. Он основывается на том, что вместо поиска прав доступа по числу, можно искать их по символьной строке. Для этого нужно применять grep. Альтернативная команда выглядит так:
    # find $* -exec ls -ld {} \; | grep "^[^ ]*s[^ ]*"
    Этот вариант команды работает несколько иначе. Он находит каждый файл из указанных каталогов и применяет к каждому из них команду "ls-ld". Затем весь список данных передается по конвейеру команде grep. Grep использует для распознавания интересующих нас файлов такой шаблон поиска: начиная с начала строки, найти повторяющийся символ, отличный от пробела, затем символ "s", за которым следует повторяющийся символ, отличный от пробела. Такому шаблону соответствуют все режимы прав доступа, содержащие s, будь то бит установки пользовательского идентификатора или бит установки группового идентификатора. Не существенно, входят ли в данный режим "r", "w", "x" или "-". Убедившись, что пробелов нет, мы обеспечиваем соответствие шаблона только полю прав доступа. Важно, чтобы после s следовали символы, отличные от пробелов, так как s может встретиться либо в порции прав доступа, относящейся к владельцу, либо в групповой порции и нигде больше.
    Мы не очень рекомендуем этот метод, поскольку он привлекает очень интенсивную обработку. Однако, если бы мы не испробовали этот метод первым, мы бы не оценили, что использование команды find со строками "-perm" является более предпочтительным. В силу невероятной гибкости системы UNIX, имеется очень много различных способов выполнения одной и той же работы, и многие из этих способов могут давать одинаково хорошие результаты, но за разную цену в смысле быстродействия и процессорных затрат. Перед тем как применять универсальную утилиту вроде grep для решения задачи, рассмотрите, нет ли другой команды со встроенной опцией распознавания по шаблону. Скорее всего, применение такой команды окажется оптимальнее и гораздо быстрее, чем использование grep. С другой стороны, иногда вам нужно быстро решить нечасто встречающуюся задачу, не слишком заботясь об эффективности решения.

    --------------------------------------------------------
    ИМЯ: suw
    --------------------------------------------------------

    suw

    НАЗНАЧЕНИЕ

    Просматривает протокольный файл команды su и печатает имена всех пользователей, которые нелегально превратились в суперпользователя при помощи команды su (substituted user, замененный пользователь).

    ФОРМАТ ВЫЗОВА

    suw [-m] [sulog]

    ПРИМЕР ВЫЗОВА

    suw Запуск в режиме по умолчанию, проверка файла /usr/adm/sulog и выдача записей о нарушителях в стандартный вывод.

    ТЕКСТ ПРОГРАММЫ

    
    1   static char id[]="@(#)suw v1.0   Author: Russ Sage";
    2
    3   # include 
    4
    5   # define FALSE 0
    6   # define TRUE  1
    7   # define MATCH 0
    8   # define BSIZ  80
    9
    10  main(argc,argv)
    11  int argc;
    12  char *argv[];
    13  {
    14          register int  alert, c, mail, n;
    15          FILE   *fp1, *fp2;
    16          char   *p, *uname, line[BSIZ], tmp[BSIZ],
    17                 *log = "/usr/adm/sulog";
    18
    19          static char  *legal[] = {sage-root\n","root-root\n",NULL};
    20          static char  *adm[]   = {"sage",NULL};
    21
    22
    23          mail = FALSE;
    24
    25          if (argc > 1 && argv[1][0] == '-')
    26                  switch (argv[1][1])
    27                  {
    28                      case 'm':
    29                          mail = TRUE;
    30                          --argc;
    31                          ++argv;
    32                          break;
    33                      default:
    34                          fprintf(stderr,"suw: invalid argument %s\n",argv[1]);
    35                          fprintf(stderr,"usage: suw [-m] [sulog]\n");
    36                          exit(1);
    37                  }
    38
    39          if (argc == 2)
    40                  log = *++argv;
    41
    42          if ((fp1 = fopen(log,"r")) == NULL)
    43          {
    44                  fprintf(stderr,"suw: error opening %s\n",log);
    45                  fprintf(stderr,"usage: suw [-m] [sulog]\n");
    46                  exit(1);
    47          }
    48
    49          sprintf(tmp,"/tmp/suw%d",getpid());
    50          if ((fp2 = fopen(tmp,"w+")) == NULL)
    51          {
    52                  fprintf(stderr,"suw: error opening %s\n",tmp);
    53                  fprintf(stderr,"usage: suw [-m] [sulog]\n");
    54                  exit(1);
    55          }
    56
    57          while (fgets(line,sizeof(line),fp1) != NULL)
    58          {
    59                  p = line + 15;
    60                  if (*p == '+')
    61                  {
    62                          p = p + 2;
    63                          while (*p != ' ') p++;
    64                          p++;
    65                          uname = p;
    66                          while (*p && *p++ != '-')
    67                                  continue;
    68
    69                          if (strcmp (p,"root\n") == MATCH)
    70                          {
    71                                  alert = TRUE;
    72                                  for (n=0; legal[n] != NULL; n++)
    73                                          if (strcmp (uname,legal[n])== MATCH)
    74                                          {
    75                                                  alert = FALSE;
    76                                                  break;
    77                                          }
    78                                  if (alert)
    79                                          fprintf(fp2,"Illegal --> %s",line);
    80                          }
    81                  }
    82          }
    83
    84          if (mail)
    85          {
    86                  fclose(fp2);
    87                  for (n=0; adm[n] != NULL; n++)
    88                  {
    89                          sprintf(line,"cat %s | mail %s",tmp,adm[n]);
    90                          system(line);
    91                  }
    92          }
    93          else
    94          {
    95                  rewind(fp2);
    96                  while ((c = getc(fp2)) != EOF)
    97                          putc(c, stdout);
    98                  fclose(fp2);
    99          }
    100
    101        fclose(fp1);
    102        unlink(tmp);
    103 }
    

    ОПИСАНИЕ

    ЗАЧЕМ НАМ НУЖНА ПРОГРАММА suw?

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

    ЧТО ДЕЛАЕТ suw?

    Программа suw читает и анализирует протокольные файлы команды su. Каждое успешное превращение в суперпользователя при помощи команды su, обнаруженное в протокольном файле, сверяется со списком разрешенных суперпользователей. Если пользователю не разрешено быть суперпользователем, то конкретная запись о нем печатается, чтобы оповестить администратора.
    По умолчанию записи о нарушителях печатаются в стандартный вывод. Протокольным файлом по умолчанию является /usr/adm/sulog. Если применяется опция -m, то записи о нарушителях раcсылаются по почте администраторам, занесенным в предопределенный список. Если нужно проверить другой протокольный файл, например /usr/adm/Osulog, то его имя можно указать в командной строке.

    ПРИМЕРЫ

    1. # suw -m
      Проверить файл /usr/adm/sulog и разослать записи о нарушителях администраторам, определенным в тексте программы.
    2. # suw /usr/adm/Osulog
      Проверить файл /usr/adm/Osulog и напечатать записи о нарушителях в стандартный вывод.

    ПОЯСНЕНИЯ

    В самом начале программы определяются и инициализируются все переменные и списки. В строке 14 определены два флага: alert (сигнал тревоги) и mail (почта). Они имеют значение TRUE или FALSE. В этой программе используются два файла: протокольный файл команды su, который вы выбираете, и временный файл. Поскольку мы собираемся применять некоторые подпрограммы стандартного ввода-вывода (stdio), мы пользуемся указателями на файлы fp1 и fp2, а не дескрипторами файлов. Применяется два буфера: один для зачитывания в него данных из протокольного файла команды su, а другой - для хранения имени временного файла. Первоначально именем протокольного файла является sulog. Если вместо него используется другое имя файла, то переменная log переустанавливается на это имя.
    Затем инициализируются предопределенные списки разрешенных суперпользователей и администраторов. В нашем примере двумя разрешенными суперпользователями являются sage (sage-root) и root (root-root). Для того чтобы приспособить это для вашей системы, поместите здесь имена людей, которым вы хотите разрешить пользоватьcя командой su для превращения в суперпользователей. Список администраторов также должен содержать соответствующие имена. В данном примере в список администраторов входит одно имя - sage. Это значит, что sage будет единственным, кто получит почту, если указана почтовая опция.
    Подразумеваемое состояние рассылки почты устанавливается в строке 23 на значение FALSE, т. е. почты нет. Это делается для того, чтобы после разбора командной строки переменная mail имела правильное значение.
    Далее выполняется проверка на ошибки. Первая проверка выглядит несколько странной, но на самом деле вполне понятна. Переменная argc возвращает число аргументов командной строки, а argv указывает на массив, содержащий сами аргументы, каждый из которых сам является массивом символов. Если командная строка вообще имеет какие-либо аргументы (argc > 1) и первым символом первого аргумента (argv[1][0]) является дефис, то проверяется, корректная ли это опция. С целью проверки второго символа первого аргумента используется оператор case.
    Если аргументом является символ m, то флаг mail устанавливается в состояние TRUE, число аргументов (argc) уменьшается на единицу, а указатель на массив аргументов (argv) на единицу увеличивается. Это служит той же цели, что и удаление аргументов из командной строки в командных файлах интерпретатора shell. Напомним, что argv является в действительности массивом указателей, а массивы трактуются точно так же, как строки, с базовым адресом и смещением. Поэтому argv[0] == argv, и argv[1] == ++argv. Если опция отличается от -m, то в стандартный вывод печатается сообщение об ошибке и программа завершается.
    В строке 39 проверяется счетчик аргументов, чтобы понять, есть ли еще один аргумент. Напомним, что argv всегда на единицу отстает от argc, потому что само имя команды является первым аргументом массива. Следовательно, для того чтобы получить второй аргумент, мы должны перейти к следующей позиции (*++argv). Если аргумент имеется, он должен быть именем протокольного файла, и это имя заносится в переменную log.
    Далее мы пытаемся открыть файлы, используемые в программе. Сначала открывается для чтения протокольный файл. Если это не срабатывает (возвращен нулевой указатель), то печатаетcя сообщение об ошибке и программа завершается. Затем в строке 49 создается имя временного файла с добавлением к нему идентификатора процесса, чтобы гарантировать уникальность имени файла. Этот файл открывается на чтение и запись. Если эта операция не удается, печатается сообщение об ошибке и выполнение завершается.
    В строках 57-103 заключен главный цикл. Управляющая часть главного цикла определяется тем, все ли данные прочитаны из протокольного файла. Если больше никакие байты прочитать нельзя, то fgets (строка 57) возвращает нулевой указатель, что завершает цикл while. Когда строка данных читается из протокольного файла, эти данные помещаются в массив line. Мы применяем указатель на символ для прохода вдоль строки и поиска записи о нарушителе.
  • Изучая запись в вашем файле sulog, вы можете увидеть, где находятся интересующие нас поля. Сначала указатель смещается на 15 символов от начала строки. Это позиция флага, определяющего, была ли успешной команда su. Если она была успешной, указатель увеличивается на два, чтобы пропустить пробел и установить указатель на имени терминала. Это имя имеет переменную длину, поэтому мы ориентируемся по пробелу в конце имени. В строках 63-64 применяется цикл while, который заставляет указатель пропустить все символы, отличные от пробела. Затем он увеличивается на единицу еще раз, чтобы пропустить пробел между именем терминала и строкой имени пользователя.
    В этот момент указатель находится в последнем поле строки. Указатель на это поле помещается в переменную uname, чтобы затем ее можно было использовать для сравнения строк. Следующий цикл while (строки 66-67) проходит по строке, пока не попадет на символ дефиса. Цикл while выполняется до тех пор, пока указатель не указывает на конец строки (т.е. на нeлевой указатель, *p == '\0') и еще не указывает на дефис. Поскольку в цикле используется p++, то когда мы попадаем на нулевой указатель, цикл завершается, причем p указывает на следующий символ.
    Выполняется проверка, был ли суперпользователем тот, кто применил команду su. Если был, то взводится флаг alert, и мы должны проверить, разрешенный ли это суперпользователь. Цикл for (строки 72-77) пробегает по всем именам в массиве, содержащем имена разрешенных пользователей, до тех пор, пока мы не обнаружим последнюю запись, которая является пустой. Строка с именем пользователя, установленная предварительно, сверяется с каждой записью в массиве разрешенных имен. Если они cовпадают, то мы можем предположить, что с данным применением команды su все в порядке. Тогда мы выключаем флаг alert и завершаем сравнение имен. Если же по окончании цикла флаг alert все еще взведен, значит имя не содержится в списке разрешенных - это, возможно, нарушитель. Вся запись целиком записывается во временный файл и управление передается назад в начало цикла для следующей операции чтения.
    Когда все данные прочитаны, цикл while завершается. В строке 84 проверяется, взведен ли флаг mail. Если да, то временный файл закрывается (чтобы сработала команда cat) и выполняется еще один цикл for (строки 87-91). Он перебирает всех администраторов и завершается, когда попадает на нулевой указатель в конце массива. Для каждого из обозначенных администраторов конструируется команда mail и посылается в систему UNIX при помощи системного вызова (строка 90). Метод отправки по почте временного файла заключается в применении к этому файлу команды cat и передаче данных по конвейеру команде mail.
    Если флаг mail выключен, то временный файл нужно напечатать в cтандартный вывод, а не отправить по почте. Для того чтобы сделать это как можно быстрее, временный файл (который пока еще открыт) "перематывается" (мы позиционируемся в его начало) и посимвольно пропускается по циклу. Обратите внимание, что данный цикл является сердцевиной команды cat, как описано на странице 153 книги Кернигана и Ритчи "Язык программирования Cи" (B.W.Kernighan, D.M.Ritchie. The C Programming Language). После того как временный файл напечатан, он закрывается. Наконец, закрывается протокольный файл и удаляется временный файл.