Уровни выполнения. Безопасность.

Уровни выполнения

Расскажем немного об уровнях выполнения системы (англ. runlevel). Уровень выполнения представляет собой специальную абстракцию, упоминаемую в файле /etc/inittab. Это конфигурационный файл для первого запускаемого при загрузке системы процесса, который носит имя init. Изменять данный файл приходится весьма нечасто, причем большинство изменений касаются только строки с параметром initdefault: в ней задается уровень выполнения по умолчанию. Файл /etc/inittab лишь создает разделение на уровни выполнения: за конфигурацию набора запускаемых на каждом уровне служб в дистрибутивах ПСПО отвечает утилита chkconfig. Она манипулирует ссылками на службы, расположенными в каталогах вида /etc/rc<уровень>.d. Таким образом, команда

$ ls -l /etc/rc0.d/

покажет службы, выполнение которых затрагивает переход на уровень 0.

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

Сами уровни выполнения можно, хотя и с некоторой натяжкой, воспринимать как профили работы системы. Кроме того, к уровням выполнения причисляют также некоторые специальные действия:

  • уровень 0 --- полная остановка системы с выключением (если это возможно);
  • уровень 6 --- перезагрузка, то есть остановка и загрузка заново (на уровень по умолчанию).

Что касается других уровней, то чаще всего они используются так:

  • уровень 1 --- однопользовательский режим работы;
  • уровень 2 --- многопользовательский режим без сети;
  • уровень 3 --- многопользовательский режим с сетью.

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

  • уровень 5 --- многопользовательский режим с сетью и графическим интерфейсом (однако в ряде дистрибутивов GNU/Linux это уровень 2!).

Отметим, что в дистрибутивах ПСПО дополнительно выполняется еще одно соответствие:

  • уровень 7 --- работа инсталятора системы.

Обратим внимание на то, что организованная таким способом система довольно неудобна. Уровни выполнения уже давно не проходятся подряд: не происходит загрузки на первый уровень с последующим переключением на второй, третий и далее до нужного. Фактически, разрешен непосредственный переход с любого уровня выполнения на любой другой --- иными словами, само слово "уровень" потеряло в данной схеме свое значение. Почему уровней выполнения (по сути дела --- профилей работы системы) существует столько, сколько сейчас --- вопрос традиции, а не удобства. В BSD-системах, например, существуют только два уровня выполнения: однопользовательский и штатный.

Чтобы понять, почему загрузка системы устроена именно так, вспомним некоторые факты из истории. Существующая схема, называемая часто System V init, была написана очень давно, еще во времена коммерческого UNIX. Создатели UNIX --- Кен Томпсон (Ken Thompson) и Деннис Ритчи (Dennis Ritchie) --- еще ранее работали над операционной системой Multics (совместный проект MIT, GE и Bell Labs, финансировавшийся Пентагоном). В системе Multics существовала появившаяся по требованию военных схема разделения на "уровни доступа":

  • Первый уровень доступа к системе определялся следующим образом. Каждый сеанс доступа к данным управлялся одним и тем же субъектом --- ясно, что с данными этот субъект мог делать все, что ему заблагорассудится. Необходимости защищать данные от произвольного доступа, таким образом, не было, а от непроизвольного --- была: если в системе одновременно функционировали несколько процессов, они не должны были иметь возможности испортить данные друг друга.
  • При втором уровне доступа в системе могли работать сразу несколько субъектов одного класса. Эти субъекты составляли "команду" и потому не имели серьезных поражений в правах по сравнению друг с другом. Тем не менее, при такой схеме работал механизм защиты от произвольного доступа, представляющий по сути дела Access Control List (ACL).
  • Третий уровень доступа соответствовал работе в системе пользователей разных категорий. Условно говоря, подключенные к машине терминалы могли соответствовать пользователям одной категории, а соединения с системой по сети --- пользователям другой категории. Для каждой из таких категорий алгоритм определения прав доступа мог задаваться отдельно.

Классическая UNIX-система содержала следы этой запутанной политики:

  • Первый уровень доступа частично соответствовал однопользовательскому режиму, который давал монопольный доступ к консоли машины.
  • Второй уровень доступа частично соответствовал многопользовательскому режиму: сидящие за терминалами пользователи образовывали "команду".
  • Третий уровень доступа частично соответствовал подключению машины к сети.

Различные режимы работы в UNIX были названы уровнями выполнения, причем ни о какой гибкости реализации речи не шло. В Multics права доступа на третьем уровне могли различаться даже алгоритмами определения: для одной категории --- ACL, для другой --- мандаты и пр. В UNIX это было сведено к некоторым упрощенным представлениям, уже не зависящим от уровня выполнения: на первое место вышла файловая система, пользователи и группы, причем вычисление прав доступа стало определяться в соответствии с жестким, заранее заданным алгоритмом. Возможность делать с системой все, что угодно, была привязана не к уровню выполнения, а к доверенному субъекту --- пользователю с идентификатором (uid), равным нулю.

Заметим, что такая архитектура позволяла организовать следующую схему. На первом уровне можно было запускать некоторые "системные" службы, на втором --- добавлять к ним службы, различающие пользователей, на третьем --- службы, организующие доступ пользователей из сети. Так устоялась традиция разделения на однопользовательский режим, многопользовательский режим и многопользовательский режим с сетью, которые соответствуют 1-му, 2-му и 3-му уровням выполнения. В настоящее время описанная модель потеряла практический смысл (за реализацию различных алгоритмов определения прав доступа может отвечать, к примеру, SELinux), а потому соответствующая схема загрузки служб (называющаяся System V init) стала восприниматься отчасти как наследие прошлого (в английском языке используется термин legacy). Тем не менее, в большинстве дистрибутивах GNU/Linux поддерживается однопользовательский режим (первый уровень выполнения), иногда используемый для монопольной работы с системой администратора при помощи консоли. В него можно перейти командой

# init 1

или указав при загрузке системы параметр ядра "single".

Безопасность: надёжность и секретность

Когда речь идёт о безопасности компьютерной системы, надо понимать, что безопасность должна трактоваться с двух сторон:

  • безопасность --- надёжность;
  • безопасность --- секретность.

Слово security, кстати, часто означает оба случая.

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

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

Хотя здесь не будет приведена полная классификация уязвимостей, укажем, что проблема безопасности --- троякая:

  • может пострадать аппаратное обеспечение;
  • могут пострадать данные (в том числе и при работающем аппаратном обеспечении: их может по ошибке стереть пользователь или преднамеренно украсть злоумышленник);
  • может произойти отказ в обслуживании: аппаратное обеспечение исправно, данные на месте, но машина работает не так, как мы хотим (например, очень медленно).

Надёжность

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

Предположим что, так или иначе, у нас есть аппаратное обеспечение. Однако у любой надежности аппаратного обеспечения есть предел, и мы хотим обеспечить большую надёжность. В первую очередь, нужно определить, а стоит ли овчинка выделки. В компьютерном классе стоит ли повышать надёжность работы конкретного компьютера, если на нём не хранится никаких данных, и он, в конце концов, заменим? Тем не менее, если это необходимо, то типичный метод повышения надежности --- холодный резерв (запасные комплекты аппаратного обеспечения) --- но он, конечно, не спасает от потери данных. Тем не менее, если есть задача обеспечить учебный процесс на N учеников, то было бы неплохо иметь 1-2 компьютера в холодном резерве.

  • Достоинства холодного резерва:
    • не нужно предпринимать дополнительных действий.
  • Недостатки:
    • не спасает от потери данных;
    • надо предусмотреть оперативное введение резерва в строй.

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

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

В текущих дистрибутивах ПСПО никаких автоматических средств для этого не включено, поскольку сервер не значился в госзаказе.

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

Простейший случай использования rsync для архивации следующий. Пусть на обоих компьютерах есть пользователь user, а на компьютере, куда осуществляется резервное копирование, установлена и запущена служба SSH:

# apt-get install openssh-server && service sshd start

Тогда на другом компьютере можно дать следующую команду для архивации (в примере 172.16.1.10 --- IP-адрес резервного компьютера):

$ rsync -avh /home/user user@172.16.1.10:/home/

В результате вся домашняя папка пользователя /home/user будет полностью скопирован на другой компьютер. Для ускорения работы утилита rsync пропускает файлы, не изменённые со времени последнего копирования. Аналогичным образом утилита rsync может копировать данные на внешний носитель:

$ rsync -avh /home/user /media/FLASH

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

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

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

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

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

Локальная безопасность

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

Доступность: физическая и виртуальная

Первое, о чем необходимо помнить: борьба за безопасность начинается с физического уровня. Если у злоумышленника есть возможность развинтить компьютер, чтобы получить информацию, то он это сделает. Таким образом, единственный защиты информации при возможности физического доступа к ней --- шифрование диска на уровне его контроллера. Поэтому защита данных на уровне их секретности начинается с административных мер, а не с программных. В первую очередь, никто не должен иметь физический доступ к серверу и физический доступ к его консоли: это позволит злоумышленнику легко войти в cистему, даже не зная пароль администратора, например, используя параметр ядра init=/bin/bash.

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

Для облегчения манипуляций с правами в ПСПО существует утилита umask, изменяющая права доступа, которые присваиваются новым файлам и директориям по умолчанию, иными словами, снимающая те или иные права. Например, umask 022 означает снятие бита записи в группах доступа g и o, то есть права вида 755.

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

Атаки отказа в обслуживании

Стоит отметить, что, говоря о надёжности системы, мы говорим в том числе и об атаках на отказ в обслуживании (DoS-атаки, от англ. Denial of Service). Хотя под такими атаками сейчас часто подразумевают сетевые атаки (которые более точно называются DDoS-атаками, от англ. Distributed Denial of Service)), отказ в обслуживании может быть вызван и действиями одного локального пользователя. Поэтому необходимо сделать так, чтобы в результате некоторых действий локального пользователя система не перестала бы быть способной выполнять полезную работу.

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

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

$ bomb() { bomb | bomb& }; bomb

Она создает шелл-функцию с именем bomb, которая начинает рекурсивно запускать саму себя дважды, при этом создается два новых процесса, которые в свою очередь порождают четыре процесса, и так далее. Очевидно, что без ограничений на количество процессов, запущенных одним пользователем, такая команда быстро вызовет отказ обслуживания. Просто посылать сигналы на завершение работы этих программ совершенно бесполезно, поскольку, даже если было достигнуто предельное число процессов, как только один из них завершит работу, на его место тут же встанет новый процесс. В принципе, можно попытаться даже написать собственную fork-бомбу, задача которой --- убивать предыдущую, но, скорее всего, это только усугубит проблему. Вариант выхода из такой ситуации --- послать всем бомбовым процессам не SIGKILL, а SIGSTOP. Тогда они прекратят своё выполнение, но не будут удалены из таблицы процессов; они будут всего лишь приостановлены, и после остановки их можно будет легко завершить. При возможности управлять ситуацией от лица суперпользователя будет полезно воспользоваться утилитой killall, выполнив команды:

# killall -u <имя запускающего такие процессы пользователя> -STOP
# killall -u <имя запускающего такие процессы пользователя> -KILL

Однако ясно, что правильным методом борьбы с бомбами является ограничение числа процессов пользователя, что и сделано в современных системам GNU/Linux.

Ограничение ресурсов, выделяемых процессам пользователя

Различные ограничения, накладываемые на пользовательские процессы, задаются при помощи системы ulimit. Полную информацию о том, насколько Вас ограничили, можно узнать, выполнив команду ulimit -a.

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
max nice                        (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 1983
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
max rt priority                 (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 256
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Эти параметры записаны в файле /etc/security/limits.conf. Ограничивать можно и отдельных пользователей, и группы. Все эти настройки записываются в окружение оболочки входа в систему (login shell) пользователя таким образом, что не могут быть изменены, и, соответственно, наследуются всеми процессами пользователя.

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

Пароли и их криптографическая стойкость

Речь здесь пойдет о паролях и об аутентификации. Очевидно, что утечка идентификационной информации равнозначна утечке той информации, которая доступна при аутентификации с помощью этого идентификатора. Но иногда есть и другие способы получить доступ к тем или иным образом защищённой информации. Например, в концепции класса активно используется сетевая файловая система NFS, авторизация в которой обычно осуществляется по IP-адресам. Иными словами, любой человек, имеющий пользователя root на локальной машине, теоретически может производить опеределенные (в том числе вредоносные) операции на сервере. Или же, файлы с сильно ограничивающими к ним доступ правами случайно копируются на файловую систему, которая не поддерживает права доступа --- также не очень приятная ситуация.

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

В отличие от традиционного для большинства систем файла /etc/shadow, в котором хранятся хэши паролей всех пользователей, в ПСПО используется система, взятая из TCB (Trusted Computing Base), когда для каждого пользователя имеется свой файл shadow, находящийся в соответствующем подкаталоге /etc/tcb. Это позволяет,например, не держать утилиту passwd как suid root.

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

Криптографическая стойкость (она же надёжность) пароля в ALT Linux и OWL проверяется при помощи passwdqc-enforce (Password Quality Control), подсистемы, которая позволяет задать некоторые ограничения, которым должен соответствовать пароль, например: минимальная длина при использовании одного, двух, трёх, четырёх классов символов, максимальная длина, состоит ли пароль из словарных слов или нет. Очевидно, что чем больше различных классов символов в пароле, тем он может быть короче --- но тем труднее его будет запомнить. Понятно, что по умолчанию отключено создание паролей из символов одного класса, как бы длинны они не были. Ведь это означает теоретическую возможность создать пароль из, к примеру, большого числа одинаковых символов, который нельзя назвать стойким ко взлому.

В числе прочего не рекомендуется использовать имя пользователя как часть пароля, пароль в одно слово и так далее. Всё это не даст сделать система контроля качества паролей, но он не везде включён, например выключен при выполнении от пользователя root. Суперпользователь будет лишь предупреждён о нестойкости пароля, но изменён он, тем не менее, будет. Стоит заметить, что это настройки passwdqc-enforce по умолчанию, которые можно изменить в соответствующем объекте подсистемы control.

Рассмотрим пример успешного обновления пароля. Так, passwdqc-enforce предлагает пароль, который, по её мнению, достаточно криптостоек --- произвольные словарные слова, разделённые произвольными знаками препинания:

[user@demo ~]$ passwd
Changing password for user.
Enter current password: 

You can now choose the new password or passphrase.

A valid password should be a mix of upper and lower case letters,
digits, and other characters.  You can use an 8 character long
password with characters from at least 3 of these 4 classes, or
a 7 character long password containing characters from all the
classes.  An upper case letter that begins the password and a
digit that ends it do not count towards the number of character
classes used.

A passphrase should be of at least 3 words, 12 to 40 characters
long and contain enough different characters.

Alternatively, if noone else can see your terminal now, you can
pick this as your password: "count!diesel!noise".

Enter new password: 
Re-type new password: 
passwd: 
all authentication tokens updated successfully.

Часто используемые алгоритмы составления достаточно стойких паролей: строчка из песни, первые буквы чего-нибудь, русские слова в английской раскладке, желательно, чтобы там были не только буквы, но и знаки препинания (русские буквы Э, Ж и тому подобное). Пока это работает, хотя, судя по всему, вскоре программы перебора паролей будут искать и по этим алгоритмам. Подбор пароля по словарю может занять доли секунды. Лектору на данный момент точно неизвестны подборщики паролей, которые перебирают по паролям в стиле leet русским (H@TTpumep, BoT T@K). Кроме того, там может присутствовать не только посимвольная замена, в отличие от классического leetspeak (к примеру, }|{, 9|).

Наконец, пароли не надо записывать, их надо запоминать. Существуют программы хранения паролей, которые их защищают другим паролем.

Различные способы узнать ваш пароль

Также не стоит забывать о том, что какой бы пароль криптостойкий не был, всегда существует способ не подобрать его, но тем или иным способом узнать непосредственно. Существует такой класс программ как "клавиатурные воры", или кейлоггеры, которые записывают каждое нажатие на клавиатуру. В системе GNU/Linux у неё есть два основных пути: системная консоль (что потребует прав root и модификации ядра, а при таком уровне доступа можно и более простым путём украсть данные) и X-сервер, а также перехват на уровне ядра операционной системы. Архитектура X-сервера такова, что может существовать программа, которая перехватывает все события с клавиатуры и перенаправляет их конкретным приложениям. Так работают, например, все оконные менеджеры. Поэтому, работая на недоверенной машине, нельзя быть уверенным, что такая программа не включена.

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

Следует отметить, что Х-сервер и приложение могут находится на разных компьютерах, а для подключения к запущенному X-серверу приложения должны проходить авторизацию. Авторизация бывает двух видов: по хостам (довольно ненадёжно, вдруг какой-нибудь другой пользователь запустит кейлоггер), и по MIT Magic Cookie (специальному хэшу). Первый регулируется утилитой xhost, второй --- xauth. Второй, в принципе, достаточно надёжен, если не принимать во внимание то, что сам по себе сетевой трафик по протоколу X не шифруется. Поэтому, даже если вы уверены, что если вам за спину никто не смотрит, работать через сеть с Х-приложениями следует только по SSH (о котором речь пойдет далее), иначе некоторая часть информации может быть просмотрена нежелательными людьми.

Безопасность: сетевая секретность

Проблема открытой передачи пароля

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

В документации man iptables содержится сводная таблица сервисов, которые не отличаются надежностью в плане безопасности. К ним относятся ftp, telnet, http, ipmap и pop3 --- все они передают идентификационные данные в незашифрованном виде.

От некоторых из этих небезопасных служб следует вообще отказаться, например, от telnet и от ftp с авторизацией пользователя. Есть замечательная утилита dsniff, в документации к которой (man dsniff) перечислены протоколы, из которых она способна "выудить" пароли.

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

В качестве надежного протокола передачи стоило бы обратить внимание на сетевой протокол IPsec (поверх которого может работать TCP), который замечательно реализован в IPv4, но он не работает "из коробки", и комплекс мер по его включению и настройке достаточно сложный, и если совершить какие-нибудь ошибки, то он либо просто не заработает, либо секретность не будет обеспечена. Поэтому из всех протоколов обеспечения безопасной передачи наиболее важно рассказать про SSL. Протокол SSL (Secure Socket Layer) --- это некая прослойка между прикладным и транспортным уровнями сети, обеспечивающее шифровку информации перед ее передачей протоколу TCP и дешифровку информацию, полученной от уровня протокола TCP. Для шифрования данных SSL организует первичный безопасный обмен временными ключами, которые в дальнейшем используются как ключи шифровки и дешифровки. #Для начального обмена

У данного слоя есть выход на прикладной уровень, чтобы приложение знало, что оно использует SSL.

../ssl01.png

Поскольку SSL не имеет своего набора портов, то разные номера портов TCP применяются для того, чтобы различать обычную службу и такую же службу, использующую SSL. Напрмер, стандартный порт сервера протола HTTP --- 80, а протокола HTTPS (HTTP поверх SSL) --- 443. С помощью утилиты stunnel можно сделать любое "обычное" соединение использующим SSL, в частности, протоколы HTTP, IMAP, POP3, XMPP могут работать поверх него.

Главное достоинство работы через SSL --- прозрачность с точки зрения вышестоящего прикладного протокола. После запуска утилиты stunnel приложение, работающее с каналом, "не заметит разницы" в своих действиях. Главный недостаток SSL --- как только эта схема перестаёт работать (это имеет место быть например в случае протокола FTP), то сразу возникают проблемы: во-первых, клиентское приложение должно знать, что есть специальный нестандартный порт, по которому надо слушать, и, во-вторых, внутри прикладного протокола нет специальных способов управления аутентификацией. За все это отвечает уровень SSL, и приложению придется организовать его самому в отсутствие stunnel.

Кроме протокола SSL, есть близкий способ обеспечения безопасности --- подобный протоколу SSL протокол TLS. TSL, строго говоря, не является протокола, не являющийся отдельным протоколом --- это модификация какого-либо протокола прикладного уровня. Соответственно, на прикладном уровне возможности TLS гораздо шире, чем у SSL. Например, с точки зрения SSL все веб-сайты на одном IP-адресе являются идентичными, поэтому протокол HTTPS может корректным образом защищать только один веб-сайт на одном IP-адресе. Поскольку на уровне SSL никто о разных именах доменов не знает (это адреса протокола HTTP), то у этих хостов один и тот же IP-адрес и ключ SSL. В TLS это вынесено на уровень приложения, то есть уже приложение решает, как шифровать и каким ключом. В отличие от SSL, когда протокол прикладного уровня не знает о его наличии, протоколам, поддерживающим TLS, известно, работает ли он в данный момент или нет.

К примеру, в протоколе IMAP есть расширение, позволяющее включить TLS как команду самого протокола. С точки зрения приложения TLS --- часть прикладного протокола, команда уровня протокола IMAP. Так же дела обстоят и в случае с протоколами POP3, FTP и XMPP. Главный недостаток TLS --- необходимость модификации протокола прикладного уровня, но зато с его помощью можно защитить использование FTP, что невозможно при применении SSL.

Подводя итог, можно сказать, что SSL --- это универсальное туннелирование, а TLS --- метод модификации протокола уровня приложения.

Организация шифрования передаваемых данных

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

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

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

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

Главный недостаток асимметричного метода --- каждой стороне необходимо обладать подтвержденными открытыми ключами всех других сторон. Если нет уверенности, что это именно их ключи, то возможна следующая ситуация: вы передаёте данные, шифруя их каким-то ключом, но этот ключ принадлежит не вашему адресату, а человеку, подсунувшему его вам на пути к конечной точке. Этот человек в середине (англ. man-in-the middle) расшифровывает данные своим закрытым ключом, перешифровывает их с помощью открытого ключа вашего адресата, и передаёт дальше. Такой человек должен перехватывать все пакеты, проходящие между вами. Мест перехвата потенциально много, так как пакеты, например, зачастую проходят через несколько маршрутизаторов на своём пути, и каждый администратор такого маршрутизатора может провести такую атаку.

../ssl02_attack.png

Есть два варианта решения этой проблемы. Первый --- вы должны как-то действительно убедиться в том, что это открытый ключ вашего адресата. Другой способ состоит в том, что этот открытый ключ попадает к вам не просто так, а подписанный с помощью какого-нибудь из открытых ключей, которые у вас уже есть и которому вы доверяете (ключ "цифрового нотариуса"). На практике используются оба подхода: в случае GPG вы подписываете ключи людей, которым доверяете, а в случае web-сайтов есть фирмы, бизнес которых состоит в подписывании ключей сервера, использующего HTTPS. Следует отметить, что метод с доверенным нотариусом не дает 100% гарантию, но является достаточно безопасным для некритичных приложений.

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


CategoryLectures CategoryPspo CategoryMpgu CategoryUneex