Перевод выполнен Алексеем Паутовым в рамках некоммерческого проекта RussianLDP (http://www.rldp.ru/). Именно на этом сайте и надлежит искать новые версии, если таковые будут.

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

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

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

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

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

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

51.2. root-привилегии

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

Не требуется root-привилегий для ещё чего-то, что делает exim, типа получения сообщений и доставки их через SMTP, и очевидно, более безопасно, если exim не работает от root кроме случаев, когда это необходимо. Поэтому, пользователь и группа exim должны быть заданы в Local/Makefile. Они известны как Exim user и Exim group. Их значения могут быть изменены в рабочей конфигурации, хотя это не рекомендуется. Часто используется пользователь с именем exim, но некоторые серверы используют вместо него mail или другое имя пользователя.

Exim использует setuid() каждый раз, когда он сбрасывает привилегии root. Это постоянное сложение полномочий: впоследствии процесс не может восстановить привлегии. До релиза 4.00 setuid() использовалась в некоторых обстоятельствах, но больше такое не имеет места.

После того, как новый процесс exim интерпретировал опции своей командной строки, он изменяет uid и gid в следующих случаях:

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

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

Некоторые инсталляции любят запускать exim под непривилигированным пользователем для дополнительной безопасности. Поддержка этого режима предоставляется путём глобальной опции deliver_drop_privilege. Когда она установлена, uid и gid изменяются на пользователя и группу exim в начале процесса доставки (и также обработчик очереди и процесс тестирования адресов). Это означает, что роутинг адресов не работает от root, и сами доставки не могут измениться на иной uid.

Оставление на исполняемом файле setuid на root, но установка deliver_drop_privilege означает, что демон всё ещё может запуститься обычным способом, и он может корректно ответить на SIGHUP, поскольку перевызов восстанавливает привилегии root.

Альтернативный подход состоит в том, чтобы сделать exim setuid на пользователя exim, и также сделать его setgid на группу exim. Если Вы сделаете это, демон должен запускаться с root-правами. Вызов exim из процесса root заставляет его вести себя так, как он себя ведёт, когда setuid на root. Однако, демон не может перезапуститься после сигнала SIGHUP, поскольку он не может восстановить привилегии.

В этом случае всё ещё полезно установить deliver_drop_privilege, поскольку это помещает exim повторно перевызвать самого себя для проведения доставки после получения сообщения. Такой перевызов растрата ресурсов, поскольку он не имеет эффекта.

Если перезапуск демона не проблема (например, если установлен mua_wrapper или вместо демона используется inetd), обладание двоичным файлом setuid на пользователя exim кажется совершенным подходом, но есть одно осложнение:

В этом стиле действия exim работает с реальным uid и gid, установленным к тем же, что и у вызывающего процесса, и эффективный uid/gid установлен в значения exim. Идеально, любая ассоцииация с uid/gid вызывающего процесса должна быть отброшена, то есть реальный uid/gid должен быть сброшен в эффективные значения, чтобы отказаться от любых привилегий, которые мог иметь вызывавший. Некоторые операционные системы обладают функцией, которая разрешает это действие для не-root эффективного uid, но многие её не имеют. Из-за этой недостаточной стандартизации, exim не обращается к этой проблеме в настоящее время.

Поэтому, рекомендованный подход для совсем непривелигированного запуска состоит в том, чтобы оставить исполняемый модуль exim setuid на root и установить deliver_drop_privilege. Это также имеет преимущество: разрешение работы демона прямым способом. Если Вы конфигурируете exim не начинать процесс доставки от root, есть множество ограничений на то, что Вы можете сделать:

Эти ограничения строго ограничивают то, что может быть сделано в локальных доставках. Однако, они не оказывают влияния на удалённые доставки. Если Вы запускаете шлюз, не делающий локальных доставок, установка 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, подставляя их собственные адреса отправителя и информацию о хосте отсылки. Для других пользователей, посылающих локальные сообщения, exim устанавливает адрес отправителя из uid и не позволяет задавать удалённый хост.

Однако, недоверенным пользователям разрешено использовать опцию командной строки -f в специальной форме -f <> для индикации, что неудача доставки не должна вызвать отчёт о ошибке. Это затрагивает конверт сообщения, но не затрагивает заголовок Sender:. Недоверенным пользователям также может быть разрешено использовать специфическую форму адресов с опцией -f путём установки опции untrusted_set_sender.

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

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

По умолчанию использование опций -M и -q, вызывающих exim для попытки доставить сообщения в его очереди, ограничено административными пользователями. Это ограничение может быть ослаблено путём установки опции no_prod_requires_admin. Точно так же использование -bp (и её вариантов) для получения списка содержимого очереди также ограничено административными пользователями. Это ограничение может быть ослаблено путём установки опции no_queue_list_requires_admin.

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

51.8. Файлы спула

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

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

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

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

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

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

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

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

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

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

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

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

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

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