27. August 2026
SPF grün, DKIM grün, Spamfilter 0,0 Punkte - und trotzdem Phishing
Tobias Wilke
@wilketob
Im Juni und im Juli habe ich hier zwei Rücklastschrift-Mails auseinandergenommen, deren "PDF-Beleg" in Wahrheit ein verschlüsseltes Phishing-Kit war. Zwischen den beiden lag noch eine dritte, die seitdem in meiner Inbox auf ihre Analyse gewartet hat. Sie ist die interessanteste von allen - und zwar nicht wegen des Anhangs, sondern wegen der Kopfzeilen.
Der empfangende Mailserver hat sie nämlich so protokolliert:
X-Received-SPF: pass ( mx08.ispgateway.de: domain of <glasfaser-id>.id
designates 103.30.180.80 as permitted sender )
X-DKIM: DKIM passed: signature is good.
X-Spam-Status: No, hits=0.0 required=9999.0 tests=none
SPF bestanden. DKIM gültig. SpamAssassin: null Punkte, kein einziger Treffer. Wer diese Mail nach den üblichen Kriterien prüft, findet nichts. (IOCs sind defangt, damit hier niemand aus Versehen klickt.)

Warum die Prüfungen grün waren
Die Antwort ist unbequem: Die Mail war echt. Nicht der Inhalt, aber der Versandweg.
SPF und DKIM beantworten eine einzige Frage: Wurde diese Mail wirklich über die Infrastruktur dieser Domain verschickt? Hier lautet die Antwort korrekterweise ja. Absender war katalog[@]<glasfaser-id>[.]id, ein Postfach bei einem indonesischen Shared-Hoster. Der SPF-Record dieser Domain listet genau den Server, der die Mail eingeliefert hat, und derselbe Server hat sie sauber signiert. Alles technisch in Ordnung.
Was die Prüfungen nicht beantworten: Gehört das Postfach noch dem, der dafür bezahlt? In diesem Fall nicht. Der Hoster hat den Weg selbst mitprotokolliert:
Received: from [5.175.231.177] (port=10403 helo=172.18.0.6)
by hosting-04.[...] with esmtpsa (TLS1.3)
X-Authenticated-Sender: katalog@<glasfaser-id>.id
esmtpsa heißt: Der Absender hat sich mit Benutzername und Passwort angemeldet. Von 5[.]175[.]231[.]177, einer VPS bei GHOSTnet in Frankfurt. Und der HELO-Name, mit dem sich der Mailer vorgestellt hat, ist 172.18.0.6 - eine Docker-interne Bridge-Adresse. Da versendet kein Mailserver, da versendet ein Container, den jemand auf einem Mietserver hochgezogen hat.
Der Weg ist also: Container in Frankfurt, meldet sich mit gestohlenen Zugangsdaten bei einem Hoster in Jakarta an, der die Mail brav signiert und nach Deutschland ausliefert. Drei Länder, alles grün.
Das ist keine Schwäche von SPF oder DKIM. Die machen genau das, wofür sie gebaut wurden. Es ist eine Schwäche der Regel "wenn die Authentifizierung passt, ist der Absender vertrauenswürdig". Diese Regel war nie richtig, und hier sieht man, warum.
Der Köder
Der Rahmen ist derselbe wie in der Juli-Welle: ein Scan vom Bürodrucker.
Betreff: Scan MFP-1F-512 – SEPA-Rücklastschrift 1284438446
1. Referenz-ID: 3BYSMHLK
2. Gerät: MFP-1F-512
3. Erfasst: 2026-07-15 10:26:13
4. Seiten: 3 (PDF)
5. Betrag: 18,80 EUR
Neun nummerierte Felder mit Gerätekennung, sekundengenauem Zeitstempel, Vertrags- und Rechnungsnummer. Das klingt nach einem System, das automatisch schreibt, nicht nach einem Menschen, der jemanden hereinlegen will. Scan-to-Mail ist in jedem Büro Alltag, und der Betrag von 18,80 Euro ist so klein, dass niemand deswegen zum Telefon greift. Man will nur kurz nachsehen, worum es geht.
Zwei Dinge stimmen trotzdem nicht. "IBAN, Mandatsreferenz und Rücklastschriftgrund entnehmen Sie nachdrücklich dem PDF" - dieses Adverb setzt an dieser Stelle kein Muttersprachler. Und der Anhang, dreimal als PDF angekündigt, heißt Sepa-Zahlung-4545966311-2026-07-15.html und ist 157 KB groß. Für einen dreiseitigen Scan wäre das eine bemerkenswerte Kompression.
Was im Anhang steckt
Beim Öffnen sieht man erst mal nur eine Ladeanimation. Darunter liegt ein Fake-Dashboard aus generiertem Wort-Salat ("Kreis Es", "Weiß Jahrhundert", "Apotheke Ist"), dazu 35 Pseudo-Kommentare wie <!-- Build: 8017 --> und durchgehend zufällige Element-IDs. Das ist Futter für statische Scanner, das bei jedem Empfänger anders aussieht.
Der eigentliche Code steckt woanders. Am Dokumentende steht ein SVG, das auf null Pixel gesetzt ist:
<svg viewBox="0 0 1 1">
<set attributeName="visibility" to="visible" begin="0s" dur="1ms"
onend="...getPropertyValue('--8mom')...
[].constructor.constructor(...)()"/>
</svg>
Kein <script>, kein onload, kein onerror. Eine SVG-Animation von einer Millisekunde Dauer, deren onend-Handler feuert, sobald die Seite gerendert ist. [].constructor.constructor ist der Umweg zu Function - ein eval, ohne dass irgendwo eval steht.
Der Handler liest eine CSS-Variable aus. Nicht ein Skript, eine CSS-Variable: In --8mom liegen 1066 Hex-Zeichen, die zu JavaScript zurückgewandelt werden. Dieser Code liest dann die zweite Variable --gdfzyu mit 139.436 Zeichen Base64. Deren erste 16 Bytes sind ein AES-Schlüssel, die nächsten 16 der Counter, der Rest der Ciphertext. Entschlüsselt wird per WebCrypto im Browser des Opfers, und heraus kommen 104 KB JavaScript, die per document.write() die komplette Seite durch ein "Rechnungsportal" ersetzen.
Schlüssel und Ciphertext liegen in derselben Datei. Das ist keine Geheimhaltung gegenüber einem Analysten - nachrechnen kann man das mit Bordmitteln:
openssl enc -d -aes-128-ctr -in ct.bin -out payload.js \
-K $(cat key.hex) -iv $(cat iv.hex)
Es richtet sich ausschließlich gegen automatische Prüfung. Ein Mail-Gateway, das die Datei scannt, sieht 139 KB Rauschen. Der Klartext entsteht erst, wenn eine echte Browser-Engine ihn erzeugt.
Die Login-Seite kennt dich schon
Der entschlüsselte Payload trägt einen Konfigurationsblock, den der Server pro Empfänger einstanzt:
// ===== INJECTION MARKER START =====
var EMAIL = 'mail@[redigiert]';
var CAMPAIGN_ID = 512950;
var EMAIL_ID = 11044428;
var LOCALE = 'de';
var BASE_URL = 'http://email-internal.facem.money';
var PROVIDER_NAME = 'ISPGateway';
var SERVER_PUBKEY_B64 = 'RNPrsgy+AMJQ5VIu4YdiXURtakJbhjmHBBiFrtof+Q4=';
Die Login-Maske ist auf ISPGateway gebrandet, den Hoster des Empfängers, inklusive gehotlinktem Logo. Die E-Mail-Adresse ist bereits eingetragen. Genau das ist der Punkt, an dem die meisten Leute aufhören zu prüfen: Eine Seite, die den eigenen Benutzernamen schon kennt, wirkt wie ein Konto, das man hat.
Danach wird zweistufig abgefragt, erst E-Mail, dann Passwort - genau wie bei Microsoft und Google. Beim Absenden verpackt der Payload die Daten mit libsodium crypto_box_seal gegen den Server-Public-Key und schickt sie in einem einzigen Feld weg:
{"utmstream": "<sealed box, base64>"}
Der Feldname tarnt sich als Marketing-Tracking. Praktisch heißt das: Wer den Verkehr mitschneidet, sieht nur Chiffrat. crypto_box_seal ist anonymes Sealing, der Client wirft seinen eigenen Schlüssel danach weg - selbst der Rechner, auf dem das läuft, könnte die Nachricht nicht mehr aufmachen. Nur der Betreiber kommt an die Zugangsdaten. Das ist Phishing-as-a-Service mit Mandantentrennung: Wer die Mails verschickt, kommt an die Beute nicht heran.
Der C2 prüft die Daten übrigens live und antwortet mit LOGIN_OK oder einer Fehlermeldung. Stimmt das Passwort, erscheint eine Bestätigungsseite: "Willkommen zurück! Ihr Rechnungskonto ist in gutem Zustand. Keine Aktion erforderlich." Kein Absturz, kein Redirect, kein Anlass, jemandem davon zu erzählen.
Dieselbe Plattform wie im Juni und im Juli
Der Server-Public-Key RNPrsgy+AMJQ5VIu4YdiXURtakJbhjmHBBiFrtof+Q4= ist Byte für Byte derselbe wie in den beiden anderen Wellen. Die Sammelstelle ist dieselbe. Und die Versender-IPs liegen alle drei im selben Netz 5[.]175[.]0[.]0/16 bei GHOSTnet, alle mit dem Docker-HELO 172.18.0.6.
Die Kampagnen-IDs sortieren das Sample sauber ein: 459939 am 24. Juni, 512950 am 15. Juli, 515364 am 24. Juli. Die Plattform vergibt sie fortlaufend über alle Kunden hinweg. Zwischen Juni und Juli waren das rund 2500 Kampagnen pro Tag, in den neun Tagen danach nur noch knapp 270. Das läuft in Schüben.
Zwei Nachträge zu meinen früheren Artikeln. Erstens: Die Domain facem[.]money ist nicht von 2014, wie ich im Juli geschrieben hatte - der Wert stammte aus dem Registry-Eintrag der TLD. Das RDAP-Event der Domain selbst sagt registration: 2026-03-10, Registrar Namecheap. Sie war zum Zeitpunkt dieser Mail vier Monate alt. Zweitens: Im Juli hatte email-internal[.]facem[.]money keinen A-Record mehr, die Sammelstelle war offline. Heute löst sie wieder auf, und zwar auf 178[.]16[.]55[.]3 bei Omegatech in Rotterdam. Der Laden ist wieder in Betrieb, auf neuer Infrastruktur.
Auf VirusTotal steht die C2-URL inzwischen bei 15 von 92 Erkennungen. Zwei Monate nach der ersten Welle. Wer sich auf URL-Blocklisten verlässt, ist strukturell zu spät dran.
Was ihr tun könnt
HTML-Anhänge am Gateway wegwerfen. Das ist der eine Hebel, der hier wirklich zieht. Rechnungen, Belege und Scans kommen als PDF. .html und .htm als Mailanhang haben in einem normalen Betrieb keinen Anwendungsfall, und genau dieser Dateityp trägt den kompletten Angriff. Eine Regel, fünf Minuten.
Grüne Auth-Header nicht als Echtheitsbeweis lesen. Diese Mail hat alles bestanden. SPF und DKIM sagen, woher eine Mail kommt, nicht ob der Absender noch der ist, für den er sich ausgibt. Wer in Schulungen "prüft den Absender" sagt, sollte dazusagen, dass das bei einem gekaperten Konto nichts bringt.
Ausgehende Verbindungen im Blick behalten. Der Payload lädt jQuery und libsodium von öffentlichen CDNs nach und POSTet dann im Klartext-HTTP an die Sammelstelle. Ein Proxy oder DNS-Filter sieht beides. Auf die Blockliste gehören facem[.]money samt Subdomains und 178[.]16[.]55[.]3. Ein Browser, der aus einer lokal geöffneten Datei heraus eine Krypto-Bibliothek nachlädt, ist ein ziemlich eindeutiges Signal.
Zwei-Faktor-Authentifizierung auf Hosting- und Webmail-Konten. Die Sammelstelle testet gestohlene Zugangsdaten sofort. Ohne zweiten Faktor ist das Konto in derselben Minute weg. Und zwar ausdrücklich auch auf den unwichtigen Postfächern - katalog@ bei einem indonesischen Hoster war so ein unwichtiges Postfach, und darüber kam diese Mail.
Die Regel, die im Alltag trägt: Ein Login-Formular erreicht man nicht aus einem Anhang. Wenn sich beim Öffnen eines Belegs eine Anmeldemaske aufmacht, ist der Vorgang beendet. Egal wie richtig das Logo aussieht und egal, ob die eigene Adresse schon drinsteht. Zum Hosting-Login geht man über ein Lesezeichen. Das ist leichter zu vermitteln als jede Header-Prüfung, und es funktioniert auch dann noch, wenn die Mail technisch tadellos ist.
Fazit
Handwerklich ist das die sauberste der drei Wellen: korrekt authentifiziert, unauffällig formuliert, plausibel verpackt. Die einzigen echten Fehler sind ein deplatziertes Adverb und ein PDF, das keins ist. Der Rest ist Infrastruktur - ein Container in Frankfurt, ein gekapertes Postfach in Jakarta, eine Sammelstelle in Rotterdam, und ein Kit, das seine Phishing-Seite mitbringt, statt auf sie zu verlinken.
Wenn eine Mail alle Prüfungen besteht, heißt das nicht, dass sie in Ordnung ist. Es heißt, dass die Prüfungen fertig sind.
Nachtrag, 13. September 2026
Der Satz weiter oben, die Sammelstelle sei wieder in Betrieb, stimmt so nicht mehr. facem[.]money hat heute überhaupt keine DNS-Delegation mehr - kein NS, kein SOA, kein A-Record, auch nicht über einen fremden Resolver. Verschwunden ist nicht der Host, sondern die ganze Zone.
Den Zwischenschritt hat VirusTotal am 4. September noch gesehen: Nameserver weiter bei Cloudflare, A-Record aber auf 127[.]0[.]0[.]1. Erst auf Loopback geparkt, dann abgeräumt - das ist das Muster einer gesperrten oder nicht verlängerten Zone, nicht das eines Umzugs.
Die C2-URL steht auf VirusTotal inzwischen bei 16 von 90 Engines. Knapp drei Monate nach der ersten Welle, und zu diesem Zeitpunkt ist die Infrastruktur dahinter längst abgeschaltet. Das widerspricht dem Punkt oben nicht, es schärft ihn: Blocklisten sind hier nicht nur spät dran, sie erwischen am Ende eine Domain, die niemand mehr braucht.
Der libsodium-Public-Key ist davon unberührt. Taucht der in einer neuen Welle unter einer anderen Domain wieder auf, ist es dieselbe Plattform.
Die kompromittierte Absender-Domain ist redigiert (<glasfaser-id>[.]id), ebenso die Empfängeradresse. Der betroffene Betrieb ist hier selbst Opfer: Sein Postfach wurde übernommen und für den Versand missbraucht - das soll kein Pranger werden. Die Infrastruktur der Angreifer ist bewusst nicht redigiert. Die vollständigen IOCs liegen intern.