WebMoney: WMZ Z294115950220 WMR R409981405661 WME E134003968233 |
Visa 4274 3200 2453 6495 |
Перевод выполнен Алексеем Паутовым в рамках
некоммерческого проекта RussianLDP
(http://www.rldp.ru/). Именно на этом сайте
и надлежит искать новые версии, если таковые будут.
Эта глава обсуждает множество проблем,
связанных с безопасностью, некоторые из которых также охвачены
в других частях этого руководства.
По причинам, которые автор не понимает,
некоторые люди продвигают exim как особенно безопасный почтовый сервер.
Возможно, из-за существования этой главы документации. Однако, цель главы
просто описать способы работы exim относительно проблем безопасности,
а не сделать утверждения относительно эффективности его безопасности в
сравнении с другими MTA.
То, что следует далее, описание того, каким
exim должен быть. Наибольшие усилия были направлены на попытку гарантировать,
что код соответствует теории, но отсутствие ошибок гарантировать нельзя.
Любая, о которой сообщено, будет исправлена, как только возможно. Есть несколько компиляционных опций, которые могут быть
установлены в Local/Makefile для создания более защищённого от атак
exim, в частности от жуликоватых администраторов exim, которые не владеют
паролем root, или кого-то, кто проник через логин exim (но не 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-привилегии,
ведут себя следующим образом:
Некоторые инсталляции любят запускать 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 обязательно должна быть истинной. Полная детализация проверок, применяемых путём appendfile до записи
в файл, даны в главе 26. Много операционных систем подавляют пакеты IP-маршрутизации источника в
ядре, но некоторые не делают этого, таким образом, exim производит свою
собственную проверку. Он протоколирует входящие вызовы TCP-маршрутизации
источника IPv4, а затем обрывает их. Это отличается от IPv6.
В настоящее время никакой специальной проверки не делается. Поддержка этих SMTP-команд по умолчанию отключена.
Если требуется, они могут быть включены путём задания подходящих ACL. 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 должен быть
собран с разрешением группе доступа на чтение к его файлам спула. Каталог спула exim и всё, что он содержит,
принадлежит пользователю exim и его группе. Режим файлов спула задаётся в
конфигурационном файле Local/Makefile, по умолчанию 0640.
Это означает, что любой, кто является пользователем группы exim, может
получить доступ к этим файлам. Exim проверяет последний компонент argv[0] и,
если он совпадает с одной из установленных специфических строк,
exim предполагает определённые опции. Например, вызов exim с последним
компонентом argv[0], установленным в rsmtp, точный эквивалент его
вызова с опцией -bS. Никаких значенией безопасности в этом нет. Единственное использование, сделанное exim с
применением %f, форматирование значений средней загрузки.
Фактически они сохранены в цифровых переменных как 1000
времён средней загрузки. Следовательно, их диапазон ограничен,
а поэтому это длина конвертированного вывода. Exim использует своё собственное имя пути,
которое встроенно в код, лишь когда ему необходимо перезапуститься для
восстановления root-привилегий. Поэтому, он не работает от root,
когда это делает. Если бы какая-то ошибка позволила перезадать путь,
это привело бы к запуску произвольной программы от root, а не от exim. Большое количество sprintf в коде фактические
вызовы string_sprintf(), функции, которая возвращает
результат сохранения malloc. Промежуточное форматирование сделано в большой
фиксированный буфер путём функции, которая запускается через непосредственное
форматирование строки, и проверки длины каждого преобразования до его
выполнения, что предотвращает переполнение буфера.
Оставшиеся использования sprintf()
происходят при контролируемых обстоятельствах, где выходной буфер
заведомо достаточной длинны, чтобы содержать конвертированную строку. Обоим этим функциям передаются произвольные строки,
но они производят их форматирование путём вызова функции
string_vformat(), которая непосредственно обрабатывает
форматируемую строку и проверяет длину каждого преобразования. Они используются лишь когда известно, что выходной
буфер достаточно большой для хранения результата.
51. Обсуждение безопасности
51.1. Сборка более защищённого exim
51.2. root-привилегии
51.3. Работа exim без привилегий
51.4. Доставка в локальные файлы
51.5. Источник роутинга IPv4
51.6. Команды VRFY, EXPN и ETRN в SMTP
51.7. Привелигированные пользователи
51.8. Файлы спула
51.9. Использование argv[0]
51.10. Использование форматирования %f
51.11. Встроенные пути exim
51.12. Использование sprintf()
51.13. Использование debug_printf() и log_write()
51.14. Использование debug_printf() и log_write()
Найди своих коллег! |