Как логировать письма, отправленные через PHP-функцию mail(), чтобы обнаруживать спам в формах
Этот гайд показывает, как заменить sendmail на обёртку, которая логирует вызовы PHP mail(), чтобы быстро находить уязвимые контактные формы и CMS, использующие ваш сервер для рассылки спама. Покрыты установка скрипта-обёртки, правки php.ini, тестирование, безопасность и рекомендации по отладке.
Автор: Till Brehm
Что делает этот метод
Идея проста: вместо прямого вызова sendmail PHP будет использовать небольшой исполняемый PHP-скрипт (/usr/local/bin/phpsendmail). Скрипт читает входящие данные сообщения, записывает краткую строку с полями To/From и выполняет реальный sendmail. Лог помогает отследить, какая виртуальная хостинг-учётная запись или сайт отправляет спам.
Важно: в исходном примере скрипт по умолчанию записывает лог в /tmp/mail_php.log, а в инструкции создаётся /var/log/mail.form. Убедитесь, что путь лог-файла в скрипте соответствует тому, что вы собираетесь использовать.
Уровень навыков и требования
Кратко: нужен доступ root к серверу, навык редактирования файлов в Linux, понимание PHP и перезапуска Apache/Nginx. Работает на Debian и других дистрибутивах (путь к sendmail может отличаться).
1 Установка скрипта-обёртки
Откройте новый файл /usr/local/bin/phpsendmail:
vi /usr/local/bin/phpsendmail… и вставьте следующий код:
#!/usr/bin/php
*/
$sendmail_bin = '/usr/sbin/sendmail';
$logfile = '/tmp/mail_php.log';
//* Get the email content
$logline = '';
$pointer = fopen('php://stdin', 'r');
while ($line = fgets($pointer)) {
if(preg_match('/^to:/i', $line) || preg_match('/^from:/i', $line)) {
$logline .= trim($line).' ';
}
$mail .= $line;
}
//* compose the sendmail command
$command = 'echo ' . escapeshellarg($mail) . ' | '.$sendmail_bin.' -t -i';
for ($i = 1; $i < $_SERVER['argc']; $i++) {
$command .= escapeshellarg($_SERVER['argv'][$i]).' ';
}
//* Write the log
file_put_contents($logfile, date('Y-m-d H:i:s') . ' ' . $_ENV['PWD'] . ' ' . $logline, FILE_APPEND);
//* Execute the command
return shell_exec($command);
?>Примечание: если на вашей системе sendmail расположен в другом месте (например, /usr/bin/sendmail или установлен Postfix), скорректируйте переменную $sendmail_bin.
Сделайте скрипт исполняемым:
chmod +x /usr/local/bin/phpsendmailСоздайте файл логов и назначьте права. Примеры:
touch /var/log/mail.form
chmod 660 /var/log/mail.form
chown root:adm /var/log/mail.formВажно: не делайте лог-файл доступным для записи всем (chmod 777) на продуктивных серверах — это риск безопасности. Лучше дать доступ только нужной группе (adm или mail).
Если вы хотите, чтобы скрипт писал в /var/log/mail.form, измените в скрипте строку:
$logfile = '/var/log/mail.form';2 Изменение php.ini
Найдите php.ini, используемый веб-сервером. На Debian/Ubuntu для модулей Apache это /etc/php5/apache2/php.ini (или /etc/php/X/apache2/php.ini для современных версий). Откройте файл:
vi /etc/php5/apache2/php.iniНайдите секцию [mail function] и измените sendmail_path на путь к нашему скрипту. Исходные строки:
[mail function]
; For Win32 only.
SMTP = localhost
smtp_port = 25
; For Win32 only.
;sendmail_from = [email protected]
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
;sendmail_path =Замените на:
[mail function]
; For Win32 only.
;SMTP = localhost
;smtp_port = 25
; For Win32 only.
;sendmail_from = [email protected]
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
sendmail_path = /usr/local/bin/phpsendmailЕсли PHP работает как CGI/FastCGI/suPHP, поменяйте такой же параметр в /etc/php5/cgi/php.ini или в соответствующем конфиге для версии PHP.
Перезапустите веб-сервер, чтобы изменения вступили в силу:
/etc/init.d/apache2 restartИли для systemd:
systemctl restart apache23 Тестирование настройки
Создайте на одном из сайтов файл mailtest.php с содержимым:
Откройте его в браузере. Если всё настроено правильно, сообщение пройдет через phpsendmail и появится строка в лог-файле.
Проверка лога:
cat /var/log/mail.formЕсли вы остаетесь без записи в лог, проверьте:
- соответствует ли путь $logfile реальному файлу;
- права доступа и владельца файла логов;
- ошибки в журнале веб-сервера (error.log) и системном журнале.
Безопасность и жесткие меры
Важно:
- Скрипт выполняется с привилегиями того пользователя, от имени которого запускается PHP. Никогда не давайте скрипту права на запись всем пользователям. Используйте chown/chmod так, чтобы только root или специальная группа могли писать лог.
- Не храните в логе полные тела писем с пользовательскими данными, если это нарушает политику конфиденциальности. В примере записываются только поля To/From и текущая директория.
- Рассмотрите фильтрацию записываемых данных на предмет потенциальной инъекции логов (удаление управляющих символов, ограничение размера). Если ожидается большой поток писем, настройте ротацию логов (logrotate).
Альтернативные подходы
- Использовать milter/SMTP-прокси: настроить Postfix/Exim с фильтрами, которые логируют и блокируют подозрительные исходящие сообщения. Подходит для крупных серверов.
- Встроенная логика в приложении: фиксировать отправки из контактных форм в отдельный лог или БД с привязкой к URL и учетной записи сайта.
- Использовать сторонние SaaS-решения для защиты форм и CAPTCHA, которые препятствуют массовым отправкам.
Каждый подход имеет свои преимущества: обёртка быстро внедряется, SMTP-прокси даёт централизованный контроль, а в приложении — точная привязка к уязвимому коду.
Руководство администратора — чеклист
- Установить /usr/local/bin/phpsendmail и сделать исполняемым.
- Настроить $sendmail_bin и $logfile в скрипте.
- Создать лог-файл, установить безопасные права (например, 660) и владельца.
- Изменить sendmail_path в php.ini для соответствующего SAPI.
- Перезапустить веб-сервер.
- Протестировать через простую mail()-страницу и проверить записи в логе.
- Настроить logrotate для лог-файла.
- Мониторить и анализировать логи; при обнаружении источника — закрыть уязвимость на стороне сайта.
Критерии приёмки
- Вызов mail() из тестовой страницы записывает строку в лог с временной меткой и полями To/From.
- Настройка не нарушает доставку почты (сообщения доходят до реального sendmail/postfix).
- Лог-файл защищён от записи нежелательных пользователей.
Примеры ошибок и как их исправлять
- Нет записей в логах: проверьте права на /usr/local/bin/phpsendmail и /var/log/mail.form, проверьте sendmail_path в том php.ini, который использует веб-сервер.
- Сообщения не отправляются: проверьте переменную $sendmail_bin и работоспособность системного MTA.
- Логи заполняются мусором: ограничьте информацию для записи и добавьте фильтрацию строк перед file_put_contents.
Мини-методология расследования спама
- Включаете лог-обёртку.
- Ждёте или запускаете нагрузочный тест с mailtest.php.
- Анализируете строки лога: определяете виртуальный хост (через $_ENV[‘PWD’] или добавляя getcwd()).
- Отключаете форму/плагин на найденном сайте, патчите уязвимость.
- По необходимости настраиваете блокировку исходящей почты на уровне MTA для этой учётной записи.
Итог и рекомендации
Использование простой обёртки для sendmail — быстрый и эффективный способ обнаруживать источники спама на хостинге. Для продакшн-серверов комбинируйте этот метод с централизованным мониторингом и ограничениями на отправку почты.
Важно: не забывайте про безопасность логов и ротацию. После обнаружения уязвимого сайта исправьте причину — установка логирования лишь помогает найти проблемное место, но не решает уязвимость в коде.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента