evgen@spb: ~/2026/07/chast-3-mail-bomba-cherez-google-groups-kogda-antispam-rabotaet-protiv-vas/

[Часть 3] Мейл-бомба через Google Groups: когда антиспам работает против вас

Разбирая логи почтового сервера по другому поводу, я наткнулся на четырёхминутный всплеск: пятнадцать писем на один адрес. Дальше стало интереснее.

Как это выглядит в логе

from=<pz+bncAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@attacker.example>
from=<pz+bncBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB@attacker.example>
from=<pz+bncCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@attacker.example>
...

Отправители с одного домена, все через mail-*.google.com, все на один мой адрес. Префикс pz+bnc — это VERP-формат Google Groups, служебный bounce-адрес рассылочного списка.

Темы писем выдают схему целиком:

"Your request has been received"                    (Zendesk)
"Potwierdzenie otrzymania wiadomości: NNNNNNNN"
"Ihre Kontaktanfrage an Mars Petcare"
"Servicecenter DB Regio Bus BaWü"                   (Deutsche Bahn)
"Zenzero ticket #NNNNNNN has been created"
"Encerramento do atendimento - Ticket NNNNNNNNNN"   (Odoo)
"Revalize Customer Success Case #NNNNNNNN"          (Salesforce)
"[Aktion erforderlich] Bestätigen Sie Ihre E-Mail"  (Amazon SES)

Автоответы хелпдесков со всего мира. Немецкие, польские, португальские, испанские.

Механика атаки

Это subscription bombing, он же list bombing. Устроен так:

  1. Атакующий создаёт группу в Google Groups на своём домене.
  2. Вписывает туда адрес жертвы.
  3. Массово шпигует адресом группы контактные формы, регистрации и хелпдески по всему интернету.
  4. Все автоответы «мы получили вашу заявку» приходят в группу и веером расходятся по её участникам — то есть жертве.

Прелесть схемы для атакующего в том, что весь трафик идёт от легитимных отправителей: Zendesk, Salesforce, Odoo, корпоративные хелпдески. У них корректный SPF, валидный DKIM, хорошая репутация IP. Блокировать их по источнику невозможно — это настоящие письма от настоящих компаний.

Почему не сработал SpamAssassin

Вот тут началось самое неприятное. Смотрю оценку:

Hits: -1.204
Tests: [DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,
        DKIM_VALID_EF=-0.1, DMARC_MISSING=0.001, HTML_MESSAGE=0.001,
        MAILING_LIST_MULTI=-1, RCVD_IN_DNSWL_BLOCKED=0.001,
        RCVD_IN_MSPIKE_H2=-0.01, RCVD_IN_ZEN_BLOCKED_OPENDNS=0.001,
        SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001]
autolearn=ham

Минус 1.2. Письмо не просто прошло — оно прошло с запасом и было заучено как ham, то есть как эталон хорошей почты.

Разберём, откуда минус.

MAILING_LIST_MULTI = −1

Правило срабатывает, когда в письме несколько заголовков рассылочного списка. Задумано разумно: легитимные рассылки не должны попадать в спам из-за формата, и им дают компенсирующий бонус.

Атакующий использует ровно этот механизм. Письма действительно идут из рассылочного списка — настоящего Google-группового. Формально правило право. Практически оно даёт бомбе минус балл.

DKIM_VALID и SPF_PASS в минус

Тоже логично сами по себе: подписанное и аутентифицированное письмо заслуживает доверия. Но отправители здесь — Google, Salesforce, Amazon SES. У них с аутентификацией всё идеально.

_BLOCKED_OPENDNS в нулях

RCVD_IN_ZEN_BLOCKED_OPENDNS, URIBL_BLOCKED, URIBL_DBL_BLOCKED_OPENDNS — суффикс означает «запрос отклонён». Репутационные проверки Spamhaus и URIBL на моём сервере вообще не выполнялись (об этом отдельная история). Проверка доменов в ссылках — та, которая могла бы что-то заметить — не работала.

Итог: сумма положительных признаков около нуля, сумма бонусов — минус единица. Фильтр честно посчитал письмо хорошим.

Вывод, который стоит запомнить: контентный антиспам не защищает от атак объёмом. Каждое письмо по отдельности легитимно. Проблема в их количестве, а SpamAssassin оценивает письма поштучно.

Что делать

1. Обнулить вредный бонус

# /etc/mail/spamassassin/local.cf
score MAILING_LIST_MULTI 0

Правило перестаёт влиять в обе стороны. Легитимные рассылки от этого не пострадают — у них хватает других положительных признаков, а вот эксплуатировать бонус больше не выйдет.

systemctl restart amavis   # в iRedMail SA живёт внутри amavisd

2. Заблокировать VERP-паттерн

В iRedMail уже есть готовая точка входа — check_sender_access pcre: в цепочке ограничений:

postconf -n | grep smtpd_sender_restrictions
smtpd_sender_restrictions = reject_non_fqdn_sender reject_unlisted_sender
    permit_mynetworks permit_sasl_authenticated
    check_sender_access pcre:/etc/postfix/sender_access.pcre
    reject_unknown_sender_domain

Дописываем в /etc/postfix/sender_access.pcre:

/^pz\+bnc[A-Za-z0-9]+@/          REJECT Blocked sender
/@(.*\.)?0335boli\.com$/         REJECT Blocked sender

PCRE-таблицы не требуют postmap, достаточно postfix reload.

Проверить:

postmap -q "pz+bncAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@attacker.example" pcre:/etc/postfix/sender_access.pcre
REJECT Blocked sender
postmap -q "normal@gmail.com" pcre:/etc/postfix/sender_access.pcre
# пусто

Первое правило важнее второго: оно ловит формат VERP Google Groups, а не конкретный домен. Атакующий сменит группу — правило продолжит работать.

Перед применением стоит убедиться, что вы не состоите в легитимных Google-группах:

grep "pz+bnc" /var/log/mail.log* | grep -v <домен_атаки> | head

Отбой происходит на этапе MAIL FROM, до приёма тела письма — не тратится трафик и не грузится amavis. И check_sender_access стоит после permit_mynetworks permit_sasl_authenticated, так что на свою отправку не влияет.

3. Ограничить объём

Блэклист лечит текущую атаку. От следующей защищает rate limit на получателя — потому что ограничивает саму форму атаки, а не конкретного отправителя.

В iRedMail для этого есть iRedAPD с плагином throttle. Правило пишется в БД:

INSERT INTO throttle (account, kind, period, priority, max_msgs, max_quota, msg_size)
VALUES ('victim@example.com', 'inbound', 3600, 100, 100, -1, -1);

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

У меня, правда, обнаружилось, что iRedAPD в этот момент вообще не работал — но это тема отдельной статьи.

Что ещё важно проверить

Subscription bombing редко бывает самоцелью. Классический сценарий: атакующий заваливает ящик мусором, чтобы среди сотен писем вы не заметили уведомление о смене пароля, списании средств или входе в аккаунт.

Так что параллельно с блокировкой стоит:

grep -iE "password|reset|подтверд|вход|login" /var/log/mail.log | grep <ваш_адрес>

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

В моём случае ничего подозрительного не нашлось — но не проверить было бы неправильно.

Если адрес нужен

Соблазн просто удалить скомпрометированный алиас велик, и если он не используется — так и надо сделать. Адрес уже в списках у бомберов, и это не лечится.

Если адрес нужен для работы, вариантов три, по возрастанию надёжности:

  1. Блэклист по источнику — играть в догонялки со сменой доменов.
  2. Карантин — не удалять, но складывать в отдельную папку правилом Sieve. Бомба не мешает работе.
  3. Rate limit — ограничить приём. Защита от формы атаки, а не от участников.

Лучше всё вместе.

Мораль

Три вещи, которые я вынес из этой истории.

Первое. Байесовский фильтр и правила по содержимому бессильны против атаки объёмом. Каждое письмо легитимно, аутентифицировано и осмысленно. Нужен механизм другого уровня — лимит на скорость приёма.

Второе. Компенсирующие правила антиспама — потенциальный вектор. MAILING_LIST_MULTI создан, чтобы не резать легитимные рассылки, и он же превращает бомбу в письма с отрицательным баллом. Стоит просматривать список правил с отрицательными весами и думать, что будет, если кто-то начнёт их эксплуатировать намеренно.

Третье, и главное. Атака пришла ровно в тот период, когда у меня одновременно не работали Spamhaus в SpamAssassin, iRedAPD с его throttle и greylisting. Ни один из этих отказов не породил алерта.

Совпадение или нет — сказать не берусь. Но выглядит поучительно: защита, о состоянии которой вы не знаете, эквивалентна её отсутствию.

evgen@spb: ~/contacts
evgen@spbping -c1 evgen.info
64 bytes from evgen.info: отвечу в течение рабочего дня
evgen@spbcat contacts.txt
mail      ya@evgen.info
telegram  @EvgenOne
github    github.com/onegin
blog      evgen.info/blog
evgen@spbecho $ЗАЧЕМ_ПИСАТЬ
интересная инфраструктурная задача · вопрос по Proxmox или Icinga ·
желание обсудить, почему memtest молчал, а память была битая
evgen@spb
© 2026 Евгений Подолинский · Санкт-Петербург
синий здесь – не тот, о котором вы подумали.