Un phishing daté du 28/09 usurpait postmaster@ et est passé sans aucun contrôle : la liste blanche que l'installeur d'ISPConfig pose sur postmaster/hostmaster/abuse (want_spam) coupe SPF et DMARC. Le document décrit les trois protections mises en place, comment les vérifier, et ce qu'elles laissent de côté. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdfUCdensc9bEAtnNvQmS2
191 lines
7.3 KiB
Markdown
191 lines
7.3 KiB
Markdown
# Courrier entrant d'owni : l'usurpation du domaine
|
|
|
|
Comment owni refuse un message qui se fait passer pour `@alpinux.org`, et
|
|
pourquoi `postmaster@` était la seule adresse qu'on pouvait usurper sans aucun
|
|
contrôle. Le pendant sortant est
|
|
[`courrier-sortant.md`](courrier-sortant.md).
|
|
|
|
État au 29/09/2026.
|
|
|
|
## L'incident du 28/09/2026
|
|
|
|
Un phishing (« Modification d'un e-mail envoyé », lien vers
|
|
`*.web.core.windows.net`) est arrivé dans la boîte `postmaster@`, avec
|
|
`From:` et `To:` tous deux à `postmaster@alpinux.org`. Il ne portait **aucun**
|
|
en-tête `X-Spam-*` ni `Authentication-Results`.
|
|
|
|
```
|
|
Received: from [171.249.196.126] (unknown [171.249.196.126])
|
|
by owni.alpinux.org (Postfix) with ESMTP id 79115207A0
|
|
```
|
|
|
|
L'expéditeur était une ADSL Viettel, qui s'est connectée directement au port
|
|
25, sans authentification. Pourtant, le SPF `-all` et le DMARC
|
|
`p=quarantine` du domaine auraient suffi à l'arrêter. Aucun des deux n'a été
|
|
consulté.
|
|
|
|
## Pourquoi il est passé
|
|
|
|
**Postfix l'a accepté.** Le destinataire est local, et l'expéditeur
|
|
`postmaster@` existe, donc `reject_unlisted_sender` le laisse passer. Il n'y
|
|
avait pas de `reject_sender_login_mismatch`. Et même activé, celui-ci n'aurait
|
|
rien vu : la boîte `postmaster@` a le SMTP désactivé
|
|
(`mail_user.disablesmtp = 'y'`), elle est donc **absente** de
|
|
`smtpd_sender_login_maps`.
|
|
|
|
**rspamd ne l'a pas analysé.** Dans `/var/log/rspamd/rspamd.log` :
|
|
|
|
```
|
|
apply static settings whitelist; rcpt matched; priority high
|
|
task is whitelisted
|
|
(default: S (no action): [0.00/15.00] []) ... settings_id: whitelist
|
|
```
|
|
|
|
L'installeur d'ISPConfig écrit dans `/etc/rspamd/local.d/users.conf` :
|
|
|
|
```
|
|
whitelist {
|
|
priority = 5;
|
|
rcpt = "postmaster"; rcpt = "hostmaster"; rcpt = "abuse";
|
|
want_spam = yes;
|
|
}
|
|
```
|
|
|
|
L'intention est bonne : la RFC 2142 veut que ces adresses reçoivent toujours
|
|
les plaintes. Mais `want_spam = yes` coupe **toutes** les vérifications, SPF
|
|
et DMARC compris, pour tout ce qui leur est adressé.
|
|
|
|
## Les trois protections en place
|
|
|
|
### 1. rspamd : liste noire sur l'enveloppe (interface ISPConfig)
|
|
|
|
Dans **Email → Spamfilter → Blacklist**, deux entrées : `postmaster@alpinux.org`
|
|
et `abuse@alpinux.org` (table `spamfilter_wblist`).
|
|
|
|
ISPConfig génère `/etc/rspamd/local.d/users/spamfilter_wblist_N.conf` : si
|
|
l'**expéditeur d'enveloppe** est cette adresse et le destinataire
|
|
`@alpinux.org`, alors `reject = 0.2`. La priorité (50) l'emporte sur la liste
|
|
blanche (5).
|
|
|
|
À ne pas confondre avec **Email → Global Filters → Blacklist**, qui
|
|
alimente la table Postfix `mail_access`. Celle-ci est lue **avant**
|
|
`permit_sasl_authenticated` : un expéditeur ajouté là serait refusé même
|
|
authentifié.
|
|
|
|
### 2. Postfix : expéditeur local ⇒ authentification (interface ISPConfig)
|
|
|
|
Dans **System → Server Config → owni → Mail**, l'option « Reject sender and
|
|
recipient login mismatch » est cochée. ISPConfig réécrit alors :
|
|
|
|
```
|
|
smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch,
|
|
permit_mynetworks,
|
|
check_sender_access proxy:mysql:/etc/postfix/mysql-virtual_sender.cf,
|
|
reject_sender_login_mismatch, permit_sasl_authenticated,
|
|
reject_non_fqdn_sender, reject_unlisted_sender
|
|
```
|
|
|
|
- Un client **non authentifié** qui envoie avec une boîte existante (SMTP
|
|
activé) est refusé.
|
|
- Un client **authentifié** ne peut envoyer qu'avec sa propre adresse, ou
|
|
avec un alias marqué « Allow send as ».
|
|
|
|
Avant d'activer l'option, j'ai vérifié sur 3 jours de logs que tous les envois
|
|
SASL utilisaient leur propre adresse (`git_app.noreply`, `alpid.noreply`).
|
|
`localhost` envoie avec `alpinux@` et `secretaire@`, mais passe par
|
|
`permit_mynetworks`.
|
|
|
|
### 3. rspamd : analyser sans jamais rejeter (fichier, hors interface)
|
|
|
|
`want_spam = yes` est remplacé dans `/etc/rspamd/local.d/users.conf` :
|
|
|
|
```diff
|
|
rcpt = "abuse";
|
|
- want_spam = yes;
|
|
+ # Plus de want_spam : on analyse (SPF/DMARC), on ne rejette jamais (RFC 2142)
|
|
+ apply {
|
|
+ actions {
|
|
+ reject = null;
|
|
+ greylist = null;
|
|
+ }
|
|
+ }
|
|
```
|
|
|
|
L'ancien fichier est sauvegardé dans `users.conf.bak-20260929`. Pour que la
|
|
correction survive à une mise à jour d'ISPConfig, une copie est placée dans
|
|
`/usr/local/ispconfig/server/conf-custom/install/rspamd_users.conf.master`.
|
|
|
|
## Pourquoi pas « destination locale ⇒ authentification »
|
|
|
|
Ce serait refuser toute la réception : le port 25 est le MX, et aucun serveur
|
|
extérieur (Gmail, Orange, les listes) ne s'y authentifie. La règle porte sur
|
|
l'**expéditeur** local (protection 2).
|
|
|
|
Celle-ci ne suffit pas seule : elle lit l'enveloppe (`MAIL FROM`), pas
|
|
l'en-tête `From:`. Un `MAIL FROM:<x@bidon.ru>` accompagné de
|
|
`From: postmaster@alpinux.org` passe Postfix. C'est DMARC, dans rspamd, qui
|
|
l'arrête, et il ne le peut que si la liste blanche ne l'en empêche pas
|
|
(protection 3).
|
|
|
|
## Où finit le spam de postmaster@
|
|
|
|
Dans `Junk`. La chaîne :
|
|
|
|
1. rspamd, via `milter_headers`, pose `X-Spam: Yes` et
|
|
`X-Spam-Status: Yes, score=…`.
|
|
2. Dovecot exécute `sieve_before = /var/vmail/%d/%n/.ispconfig-before.sieve`,
|
|
généré par ISPConfig parce que `mail_user.move_junk = 'y'` :
|
|
`if header :matches "X-Spam-Status" "Yes, *" { fileinto :create "Junk"; stop; }`
|
|
3. En secours, `sieve_before2 = /var/lib/dovecot/sieve/spam-to-junk.sieve`
|
|
fait la même chose.
|
|
|
|
La relève de la messagerie lit `INBOX,Junk` (`IMAP_PM_DOSSIER`) : un rapport
|
|
DMARC classé à tort reste donc traité.
|
|
|
|
## Vérifier
|
|
|
|
```sh
|
|
# Rejouer une usurpation dans rspamd, depuis l'IP de l'attaquant
|
|
rspamc -h localhost:11333 -i 171.249.196.126 \
|
|
-F <enveloppe> -r <destinataire> < test.eml
|
|
|
|
# Le tri sieve, à sec, sur une copie du script et un maildir jetable
|
|
# ($W doit être lisible par vmail ; -u postmaster@… échoue sur l'auth)
|
|
rspamc -h localhost:11333 --mime -i 171.249.196.126 -F bidon@example.ru \
|
|
-r postmaster@alpinux.org < test.eml > $W/out.eml
|
|
sudo sieve-test -o mail_uid=vmail -o mail_gid=vmail \
|
|
-o mail_location=maildir:$W/md $W/before.sieve $W/out.eml
|
|
|
|
# Un utilisateur qui envoie avec une adresse qui n'est pas la sienne
|
|
sudo grep "not owned by user" /var/log/mail.log
|
|
```
|
|
|
|
Résultats relevés le 29/09/2026 :
|
|
|
|
| Scénario | Avant | Après |
|
|
|---|---|---|
|
|
| Enveloppe et `From:` = postmaster@, vers postmaster@ | accepté, 0.00 | **rejeté** |
|
|
| Enveloppe bidon, `From:` = postmaster@, vers postmaster@ | accepté, 0.00 | **Junk**, 17.80 (SPF, DMARC) |
|
|
| Même chose vers president@ | rejeté | rejeté |
|
|
| Rapport externe légitime vers postmaster@ | accepté | accepté, -0.40 |
|
|
|
|
## Pièges
|
|
|
|
- **Un refus `not owned by user`** : quelqu'un envoie avec un alias sans
|
|
« Allow send as ». Cocher la case sur l'alias dans ISPConfig ; ne pas
|
|
décocher l'option globale.
|
|
- **Après une mise à jour d'ISPConfig**, vérifier que `users.conf` n'a pas
|
|
retrouvé `want_spam` : la copie dans `conf-custom/install/` doit l'éviter.
|
|
- **Les boîtes au SMTP désactivé et les redirections sans « Allow send as »**
|
|
(`abuse@`, `kernel@`, `cedric.a5l@`) ne sont pas couvertes par la
|
|
protection 2. Seuls DMARC et, pour `abuse@`, la liste noire les protègent.
|
|
|
|
## Retour arrière
|
|
|
|
```sh
|
|
sudo cp -a /etc/rspamd/local.d/users.conf.bak-20260929 /etc/rspamd/local.d/users.conf
|
|
sudo rm /usr/local/ispconfig/server/conf-custom/install/rspamd_users.conf.master
|
|
sudo systemctl reload rspamd
|
|
```
|
|
|
|
Les protections 1 et 2 s'annulent depuis l'interface ISPConfig.
|