51. Обсуждение безопасности


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

51.1 Сборка более защищённого exim`a

   Есть несколько компиляционных опций, которые могут быть установлены в Local/Makefile , для создания более защищённого от атак exim`a, в частности от жуликоватых администраторов exim`a, которые не владеют паролем root`a, или кого-то, кто проник через аккакунт exim`a (но не root`a). Эти опции таковы:

  • ALT_CONFIG_PREFIX - может быть установлена в строку, которая должна совпадать с началом любых имён файлов используемых с опцией -C . Когда она установлена, этим именам файлов, также, не разрешается содержать последовательность /../. (Однако, если значение опции -C идентично со значением CONFIGURE_FILE в Local/Makefile , exim игнорирует -C и работает как обычно.) Для ALT_CONFIG_PREFIX нет значения по умолчанию.
       Если разрешённые конфигурационные файлы ограничены директорией к которой имеет доступ только root, это предохраняет тех, кто взломал аккаунт exim`a от работы с произвольным конфигурационным файлом, и использования его для взлома других аккаунтов.
  • ALT_CONFIG_ROOT_ONLY - если она задана, привилегии root`a сохраняются для опций -C и -D лишь если вызывающий exim - root. Без этого, пользователь exim`a также может использовать -C и -D и сохранять привилегии. Установка этой опции блокирует возможность тестирования конфигурации используя -C напрямую через приём и доставку сообщения, если вызывающий - root. Приём работает, но к этому времени exim работает как пользователь exim`a, таким образом, когда он перезапускается для восстанавления привилегий для доставки, использование -C вызывает потерю привилегий. Однако, root может тестировать приём и доставку используя две раздельные команды. По умолчанию, ALT_CONFIG_ROOT_ONLY не установлена.
  • DISABLE_D_OPTION - если задана, отключено использование -D в командной строке.
  • FIXED_NEVER_USERS - может быть установлена в список пользователей, разделённый двоеточиями, которые никогда не могут использоваться для доставки. Это похоже на рабочую опцию never_users , но не может быть перезадана; рабочая опция добавляет дополнительных пользователей в этот список. Дефолтовая установка - root; это предотвращает не-root`овых пользователей, кому разрешено изменять файл рабочей конфигурации, от использования exim как способ получить root`овые привилегии.

    51.2 root`овые привилегии

       На бинарник exim`a, обычно, установлен бит setuid на root`a, что означает, что в начале выполнения он получает root`овые привилегии (работает от root). В некоторых специальных случаях (например, когда не используется даемон, и нет локальных доставок), возможно запускать exim с setuid на иного пользователя, чем root. Это обсуждается в следующей секции. Однако, в большинстве инсталляций, root`овые привилегии требуются по двум причинам:

  • Для установления соединения сокета на стандартный порт SMTP (25) при инициализации слушающего даемона. Если exim запускается из inetd , это привелигированное действие не требуется.
  • Чтобы быть в состоянии изменить uid и gid для чтения пользовательских файлов .forward , и выполнения локальных доставок от получающего пользователя или как задано в конфигурации.
       Не требуется root`овых привилегий для ещё чего-то, что делает exim, типа получения сообщений и доставки их наружу через SMTP, и очевидно, более безопасно, если exim не работает от root`a кроме случаев, когда это необходимо. Поэтому, пользователь и группа exim`a должны быть заданы в
    Local/Makefile . Они известны как the Exim user и the Exim group. Их значения могут быть изменны в рабочей конфигурации, хотя это не рекомендуется. Часто используется пользователь с именем exim , но некоторые сервера используют вместо него mail или другой имя пользователя.
       Exim использует
    setuid() каждый раз, когда он сбрасывает привилегии root`a. Это - постоянное сложение полномочий; впоследствии, процесс не может восстановить привлегии. До релиза 4.00, setuid() использовалась в некоторых обстоятельствах, но больше такого не имеет места.
       После того, как новый процесс exim`a интерпретировал опции своей командной строки, он изменяет uid и gid в следующих случаях:
  • Если используется опция -C для задания альтернативного конфигурационного файла, или bcgjkmpetncz опция -D для определения макрозначения для конфигурации, и вызывающий процесс не запущен как root или пользователь exim`a, uid и gid изменяются на заданные вызывающим процессом. Однако, если в Local/Makefile задана ALT_CONFIG_ROOT_ONLY, лишь вызывающий root может использовать -C и -D без потери привилегий, и если задана DISABLE_D_OPTION, опция -D не может использоваться вообще.
  • Если используется опция тестирования раскрытия ( -be ), или одна из опций тестирования фильтра ( -bf или -bF ), uid и gid изменяются на таковые из вызывающего процесса.
  • Если процесс - не процесс даемона, и не процесс обработчика очереди, или процесс доставки, или процесс тестирования роутинга адреса (запущенный с -bt ), uid и gid изменяются на пользователя и группу exim`a. Это означает, что при получении сообщений exim всегда работает под своим собственным uid и gid. Это также применяется когда тестируется проверка адреса (опция -bv ), и тестируется политика входящих сообщений (опция -bh ).
  • Для даемона, обработчика очереди, доставки, или процесса тестирования адресов, на данном этапе uid остаётся root, но gid изменяется на группу exim`a.

       Процессы, которые изначально сохраняют root`овые привилегии, ведут себя следующим образом:
  • Процесс даемона изменяет gid на группу exim`a и uid на пользователя exim`a после установки одного или нескольких слушающих сокетов. Вызывается функция initgroups() , таким образом, чтобы если пользователь exim`a находится в каких-то дополнительных группах, они использовались в процессе доставки.
  • Процесс обработчика очереди сохраняет привилегии root`a в процессе выполнения. Его работа - запустить контролируемую последовательность процессов доставки.
  • Процесс доставки сохраняет привилегии root`a в большинстве своих выполнений, но любые актуальные доставки (т.е. - непосредственно транспорты) запускаются в субпроцессах, которые всегда изменяются на не-root`овые uid и gid. Для локальных доставок, это, обычно, uid и gid владельца почтового ящика; для удалённых доставок, используются uid и gid пользователя exim`a. Как только все субпроцессы доставки запущены, процесс доставки изменяется на uid и gid exim`a, пока производятся последоставочные работы, типа обновления БД повторов, и генерации рикошетов и предупреждающих сообщений.
       Когда роутятся адреса получателей сообщения, процес доставки работает от root`a. Однако, если обрабатывается пользовательский файл фильтра, он завершается в субпроцессе который работает под индивидуальным пользовательским gid и uid. Системный фильтр запускается от root`a, если не задана
    system_filter_user .
  • Проверяющий адреса процесс (опция -bt ), запускатеся от root`a, таким образом роутинг делается в том же окуржении, что и доставка сообщения.

    51.3 Работа exim без привилегий

       Некоторые инсталляции любят запускать exim под непривилигированным пользователем, для дополнительной безопасности. Поддержка для этого режима предоставляется путём глобальной опции deliver_drop_privilege . Когда она установлена, uid и gid изменяются на пользователя и группу exim`a в начале процесса доставки (и, также, обработчик очереди и процесс тетстирования адресов). Это означает, что роутинг адресов не работает от root`a, и сами доставки не могут измениться на иной uid.
       Оставление на бинарнике setuid на root`a, но установка
    deliver_drop_privilege означает, что даемон всё ещё может запуститься обычным способом, и он может корректно ответить на SIGHUP, поскольку перевызов восстанавливает привилегии root`a.
       Альтернативный подход состоит в том, чтобы сделать exim setuid на пользователя exim`a, и, также, сделать его setgid на группу exim`a. Если вы сделаете это, даемон должен запускаться с root`овыми правами. (Вызов exim`a из процесса root`a заставляет его вести себя так, как он себя ведёт когда setuid на root.) Однако, даемон не может перезапуститься после сигнала SIGHUP, поскольку он не может восстановить привилегии.
       В этом случае, всё ещё полезно установить
    deliver_drop_privilege , поскольку это помещает exim`y повторно перевызвать самого себя, для проведения доставки после получения сообщения. Такой перевызов - растрата ресурсов, поскольку он не имеет эффекта.
       Если перезапуск даемона - не проблема (например, если установлен
    mua_wrapper , или вместо даемона используется inetd ), обладание бинарником setuid на пользователя exim кажется совершенным подходом, но есть одно осложнение:
       В этом стиле действия, exim работает с реальным uid и gid, установленным к тем же что и увызывающего процесса, и эффективный uid/gid установлен в значения exim`a. Идеально, любая ассоцииация с uid/gid вызывающего процесса должан быть отброшена, т.е. реальный uid/gid должен быть сброшен в эффективные значения, чтобы отказаться от любых привилегий, которые мог иметь вызывавший. Некоторые операционные системы обладают функцией, которая разрешает это действие для не-root`ового эффективного uid, но многие её не имеют. Из-аз этой недостаточной стандартизации, exim не обращается к этой проблеме в настоящее время.
       Поэтому, рекомендованный подход для
    совсем непривелигированного запуска состоит в том, чтобы оставить бинарник exim`a setuid на root, и установить deliver_drop_privilege . Это, также, имеет преимущество - разрешение работы даемона прямым способом.
       Если вы конфигурируете exim не начинать процесс доставки от root`a, есть множество ограничений на то, что вы можете сделать:

  • Вы можете доставлять лишь как пользователь/группа exim`a. Вы должны явно использовать опции user и group для перезадания роутеров и локальных транспортов которые обычно доставляют под получателем. Этим удостоверяется, что конфигурация работающая в этом режиме работает точно таким же способом как ив обычном режиме. Любое явное или неявное задание другого пользователя вызывает ошибку.
  • Использование файлов .forward строго ограничено, так что, обычно, не стоит их включать в конфигурацию.
  • Пользователи использующие .forward должны сделать чтобы их домашний каталог был доступен пользователю exim`a. Трубы и добавления в файл, и их эквививаленты в фильрах exim`a, не могут использоваться. Можно было бы включить их под пользователем exim`a, что небезопасно и не очень полезно.
  • Если не все локальные почтовые ящики принадлежат пользователю exim`a (возможно в некоторых окружениях использующих только POP3 или IMAP):
    1. Они должны принадлежать группе exim`a и у этой группы должно быть право записи в них. Это подразумевает, что вы должны установить
    mode в конфигурации appendfile, так же как режим для самих почтовых ящиков.
    2. Вы должны установить
    no_check_owner , поскольку большинство или все файлы не будут принадлежать пользователю exim`a.
    3. Вы должны установить
    file_must_exist , поскольку exim не может корректно установить владельца новых создаваемых почтовых ящиков, когда у него нет привилегий. Также это подразумевает, что новые почтовые ящики необходим создавать вручную.
       Эти ограничения строго ограничивают то, что может быть сделано в локальных доставках Однако, они не оказывают влияния на удалённые доставки. Если вы запускаете шлюз, не делающий локальных доставок, установка
    deliver_drop_privilege не добавляет безопасности.
       Если вы используете средство
    mua_wrapper (смотрите раздел 47), опция   deliver_drop_privilege обязательно должна быть истинной.

    51.4 Доставка в локальные файлы

       Полная детализация проверок применяемых путём appendfile до записи в файл даны в главе 26.

    51.5 Источник роутинга IPv4

       Много операционных систем подавляют пакеты IP маршрутизации источника в ядре, но некоторые не делают этого, таким образом, exim производит свою собственную проверку. Он логгирует входящие вызовы TCP маршрутизации источника IPv4, и, затем, обрывает их. Это отличается от IPv6. В настоящее время, никакой специальной проверки не делается.

    51.6 Команды VRFY, EXPN, и ETRN в SMTP

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

    51.7 Привелигированные пользователи

       Exim распознаёт два набора пользователей со специальными привилегиями. Доверенные пользователи имеют возможность локально посылать новые сообщения exim`y, подставляя их собственные адреса отправителя и информацию о хосте отсылки. Для других пользователей посылающих локальные сообщения, exim устанавливает адрес отправителя из uid, и не позволяет задавать удалённый хост.
       Однако, недоверенным пользователям разрешено использовать опцию командной строки
    -f , в специальной форме -f <> , для индикации, что неудача доставки не должна вызвать отчёт о ошибке. Это затрагивает конверт сообщения, но не затрагивает заголовок Sender: . Недоверенным пользователям также может быть разрешено использовать специфическую форму адресов с опцией -f , путём установки опции untrusted_set_sender .
       Доверенные пользователи используются для запуска процессов которые получают почтовые сообщения с одних почтовых доменов и передают их exim`y для их локальной доставки, или через интернет. Exim доверяет вызывающему работающему от root`a, от пользователя exim`a, или под любым пользователем перечисленным в конфигурационной опции
    trusted_users , или под любой группой перечисленной в опции trusted_groups .
       Административным пользователям разрешено производить действия над сообщениями в очереди exim`a. Они могут замораживать или оттаивать сообщения, вызывать их возвращение к их отправителю, полностью удалять их, или модифицировать их различными способами. Дополнительно, административные пользователи могут запускать монитор exim`a и видеть всю информацию которую он может предоставить, включая содержимое файлов спула.
       По умолчанию, использование опций
    -M и -q , вызывающих exim для попытки доставить сообщения в его очереди, ограничено административными пользователями. Это ограничение может быть ослаблено путём установки опции no_prod_requires_admin . Точно также, использование -bp (и её вариантов) для получения списка содержимого очереди, также ограничено административными пользователями. Это ограничение может быть ослаблено путём установки опции no_queue_list_requires_admin .
       Exim распознаёт административного пользователя если вызывающий процесс запущен как root или как пользователь exim`a, или любая группа ассоциированная с процессом  - группа exim`a. Нет необходимости фактически работать от группы exim`a. Однако, если административные пользователи не являющиеся root`ом или пользователем exim`a должны получить доступ к содержимому файлов spool`a через монитр exim`a (который работает непривелигированным), exim должен быть собран с разрешением группе доступа на чтение к его файлам спула.

    51.8 Файлы спула

       Директория спула exim`a, и всё что она содержит, принадлежит пользователю exim`a и его группе. Режим файлов спула задаётся в конфигурационном файле Local/Makefile , и по умолчанию - 0640. Это означает, что любой, кто является пользователем группы exim`a может получить доступ к этим файлам.

    51.9 Использование argv[0]

       Exim проверяет последний компонент argv[0] , и если он совпадает с одной из установленных специфических строк, exim предполагает определённые опции. Например, вызов exim с последним компоненом argv[0] установленным в rsmtp - точный эквивалент его вызова с опцией -bS . Никаких значенией безопасности в этом нет.

    51.10 Использование форматирования %f

       Единственное использование сделанное exim`ом с использованием %f - форматирование значений средней загрузки. Фактически они сохранены в цифровых переменных как 1000 времён средней загрузки. Следовательно, их диапазон ограничен, и поэтому - это длина конвертированного вывода.

    51.11 Встроенные пути exim`a

       Exim использует своё собственное имя пути, которое встроенно в код, лишь когда ему необходимо перезапуститься для восстановления root`овых привилегий. Поэтому, он не работает от root`a, когда это делает. Если бы какая-то ошибка позволила перезадать путь, это привело бы к запуску произвольной программы от root`a, а не exim`a.

    51.12 Использование sprintf()

       Большое количество sprintf в коде - фактические вызовы string_sprintf() , функции которая возвращает результат сохранения malloc. Промежуточное форматирование сделано в большой фиксированный буфер, путём функции которая запускается через непосредственное форматирование строки, и проверки длинны каждого преобразования до его выполнения, что предотвращает переполнение буфера.
       Оставшиеся использования
    sprintf() происходят при контролируемых обстоятельствах, где выходной буфер заведобо достаточной длинны, чтобы содержать конвертированную строку.

    51.13 Использование debug_printf() и log_write()

       Обоим этим функциям передаются произвольные строки, но они производят их форматирование путём вызова функции string_vformat() , которая непосредственно обрабатывает форматируемую строку, и проверяет длину каждого преобразования.

    51.14 Использование debug_printf() и log_write()

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




    =============
    Автор перевода: lissyara, оригинал: http://www.lissyara.su/?id=1200