+49 (0) 9491 / 742 988 50

Spam

Wie ein simpler Email Harvester eine halbe Million Mails pro Tag erntet und was man dagegen machen kann

Beginnen werden wir mit etwas recht Banalem, mit dem vermutlich jeder schon mal seine Erfahrungen gemacht hat: Spam

Sei es die E-Mail, die in holprigem Deutsch Potenzpillen verkaufen will, oder die Hochglanzmail, die für eine neue Kryptowährung wirbt, etwas in dieser Art hatte vermutlich jeder schon mal in seinem Postfach.

Wie aber ist der Absender der Mail an meine Adresse gelangt? Grundsätzlich gibt es da mehrere Möglichkeiten:

  • Emaillisten mit privaten Mailadressen können im Darknet gekauft werden
  • Emaillisten mit Firmenmailadressen können legal (mehr oder weniger) bei Adresshändlern gekauft werden
  • Teilweise sind entsprechende Listen  öffentlich zugänglich, etwa auf Paste Sites
  • Oder die entsprechenden Listen werden mit einem Email Harvester selbst erstellt

 

Den letzten Fall werden wir in diesem Blog Beitrag ein wenig näher betrachten und dabei auch einen eigenen „Email Vollernter“ in Python programmieren.

Ohne Email geht es nicht

Emails sind weder aus dem geschäftlichen noch aus dem privaten Umfeld wegzudenken. Und so verwundert es auch nicht, dass man auf den meisten Webseiten entweder ein Kontaktformular, oder eine angegebene Emailadresse findet, über die man mit dem Webseitenbetreiber in Kontakt treten kann.

Beispielsweise in der folgenden Form:

Diese Emailadressen sind aber nicht nur für potenzielle Kunden und Geschäftspartner interessant, sondern auch für Hacker oder Spammer (wobei wir uns in diesem Blog Beitrag vor allem mit letzteren beschäftigen).

Wir werden im Folgenden demonstrieren, wie Emailadressen auf verschiedenen Wegen aus Webseiten ausgelesen werden können. Insbesondere ist dabei auch interessant, mit welch geringem Aufwand ein solches Programm erstellt werden kann. Unsere Basis Version kommt gerade mal auf 11 Zeilen Code, die umfangreichere Version auf 40 Zeilen.

Email im sourcecode erkennen

Wenn man sich den HTML Code der obigen Beispielseite anschaut (Rechtsklick und dann Untersuchen auswählen), dann sieht man, dass eine Emailadresse eine ganz bestimmte Struktur hat:

Mit dem <a Tag wird ein Link definiert, href gibt die genaue Adresse an und das mailto Attribut sorgt dafür, dass sich bei einem Klick auf diesen Link automatisch das Emailprogramm des Users öffnet und die angegebene Adresse als Empfänger übernommen wird.

Diese klare Struktur ist zwar für den User angenehm, macht es aber auch für einen Spammer sehr leicht, die Emailadresse abzugreifen. Um das zu demonstrieren, haben wir ein kleines Python Programm geschrieben (lediglich 11 Zeilen Code):

Dieses Programm ruft die angegebene URL auf, findet zunächst alle Links im HTML Code und filtert anschließend diejenigen aus, die das mailto Attribut haben. Der String „mailto:“ wird dann noch entfernt und die Adresse anschließend ausgegeben:

Eine in dieser Form gekennzeichnete Emailadresse kann also in kürzester Zeit von einem Spammer ausgelesen werden. Die logische Schlussfolgerung wäre also, das mailto Attribut zu entfernen, da dieses zum Selektieren verwendet wird (siehe dazu auch den Abschnitt mit den Gegenmaßnahmen). Das alleine ist allerdings noch nicht ausreichend.

Emails an ihrer Struktur erkennen

Auch wenn das mailto Attribut nicht vorhanden ist, haben Emailadressen eine ganz bestimmte Struktur:

  • Vor dem @ Zeichen können Buchstaben, Zahlen und einige wenige Sonderzeichen (Punkt, Strich, Unterstrich) stehen
  • Dann kommt genau ein @ Symbol
  • Der Domain Teil kann ebenfalls Zahlen, Buchstaben und einige wenige Sonderzeichen enthalten
  • Dann kommt mindestens ein Punkt (für TLDs wie .com), zwei Punkte sind aber auch möglich (für TLDs wie .co.uk)
  • Und schließlich folgt die TLD, diese besteht aus Buchstaben und ist mindestens zwei Zeichen lang

 

Das ist also ein relativ genauer Bauplan für jede beliebige Emailadresse. Anstatt nach Links zu suchen, können wir nun also nach beliebigen Textstrings suchen und prüfen, ob sie unserem definierten Bauplan entsprechen.

Dafür verwenden wir einen regulären Ausdruck bzw. Regular Expression (abgekürzt RegEx):

Unser neuer RegEx basierter Harvester besteht immer noch aus 11 Zeilen Code, ist jetzt aber leicht umgebaut worden:

  • Wir haben eine RegEx definiert (regex_mail), die den Bauplan für Emailadressen enthält
  • Wir lesen den HTML Code der Seite Zeile für Zeile
  • Wir splitten die Zeile an den Skript Tags um lediglich die Inhalte zu verarbeiten (wenn die Emailadresse als reiner Text angegeben ist, dann steht sie in <p> Tags)
  • Wir prüfen für jedes Element der Zeile, ob das Element dem Bauplan einer Emailadresse entspricht

 

Nun haben wir zwei verschiedene Möglichkeiten, Emailadressen aus dem HTML Code einer Webseite zu extrahieren. Momentan erfordert unser Programm aber noch viel Handarbeit, da die Seite die untersucht wird, hart codiert ist und jedes Mal manuell geändert werden müsste.

Emails automatisiert ernten (V1)

Bis zu diesem Zeitpunkt haben wir lediglich eine einzige Webseite aufgerufen, um dort die Emailadresse auszulesen (dabei handelt es sich übrigens um eine Testseite). Für den praktischen Einsatz ist das natürlich nicht praktikabel. Wenn man andauernd neue Webseiten in das Programm einfügen möchte, wird man am Tag nur eine sehr begrenzte Menge an Emailadressen ernten können.

Im nächsten Schritt wird unser Harvester also dahingehend erweitert, dass er nach und nach verschiedene Webseiten abarbeitet. Zu Testzwecken haben wir dafür ein Text File mit den 100 meistaufgerufenen Webseiten in Deutschland angelegt.

Quelle: Meistbesuchte Websites in Deutschland Top 100 in 2021 und 2022 (semrush.com)

Die entsprechenden URLs können auf der oben verlinkten Seite kopiert werden, anschließend wurden die anderen Informationen, wie die Anzahl der Besucher, entfernt, sodass nur noch URLs in der Form [domain].[TLD] im File zu finden sind.

Bevor wir anfangen, Emails zu ernten, müssen wir aber noch zwei Veränderungen an der Form der URLs vornehmen:

  • Für den Aufruf durch das Requests Modul sollten die URLs in der Form https://www.[domain].[TLD] sein. Entsprechend muss den Seiten also https://www. vorangestellt werden
  • Dass wir auf der Startseite Emailadressen finden, ist eher unwahrscheinlich, besser stehen die Chancen auf den Seiten Impressum, Kontakt bzw. Contact (für englischsprachige Seiten). Diese Seiten hängen wir an die ursprüngliche URL an

 

Dadurch entstehen dann URLs der folgenden Form:

Aus der ursprünglichen Liste von 100 URLs haben wir nun also 300 URLs gemacht, die wahrscheinlich Emailadressen enthalten. Diese werden nun nacheinander aufgerufen:

Die Funktionalität zum Extrahieren der Mailadresse ist nun in eine Funktion gepackt und wird für jede der neu erstellten 300 URLs aufgerufen. Am Ende wird zudem die Laufzeit des Programms gemessen, sowie die Anzahl der gefundenen Mailadressen ausgegeben.

Aus den 100 beliebtesten Webseiten können auf diese Weise 129 Mails ausgelesen werden. Viele davon Funktionsmails (info@, kontakt@, sales@) aber auch einige persönliche Mails von realen Personen (Beispielsweise, wenn im Impressum ein Datenschutzbeauftragter genannt wird, oder auf der Kontaktseite ein Ansprechpartner für Bewerbungen).

Die Laufzeit beträgt 247 Sekunden, also ziemlich genau 4 Minuten. Nicht furchtbar (bei dieser Geschwindigkeit würden wir ca. 46.000 Mails pro Tag ernten) aber auch noch nicht wirklich schnell. Im nächsten Schritt wird es also um die Optimierung der Performance gehen.

Außerdem zeigt sich, dass es zu einer Handvoll False Positives kommt: Links die zwar Mailto gesetzt haben aber keine syntaktisch korrekten Emailadressen sind:

Entsprechende Mails müssen also noch aussortiert werden, um die Qualität unserer neu erstellen Liste garantieren zu können.

Emails automatisiert ernten (V2)

Der bisherige Ablauf unseres Harvester Programms ist wie folgt:

  • Rufe eine Seite auf
  • Extrahiere die Mailadresse
  • Rufe eine Seite auf
  • Extrahiere die Mailadresse

 

Limitierender Faktor ist also vor allem die Antwortzeit der Webseite die aufgerufen wird. Wenn eine Seite sehr lange lädt, hält das unser komplettes Programm auf. In gewisser Weise haben wir das zwar berücksichtigt, indem ein Timeout für den Request von 10 Sekunden festgesetzt wurde, aber auch diese kurzen Zeitspannen können sich im Lauf der Zeit aufsummieren.

Für die zweite Version unseres Harvesters werden wir daher nun den Ablauf parallelisieren, sodass der Aufruf der Webseiten nicht nacheinander, sondern nebeneinander erfolgt.

Unser Code bleibt dabei weitgehend gleich (in der Funktion zur Email Extrahierung wurde ein try/exept Block ergänzt, um Fehler abzufangen). Wirklich neu ist nur die runner() Funktion die 20 Threads startet und mit diesen jeweils die extract_links() Funktion aufruft:

Zudem werden die per mailto Attribut gefundenen Mails nun mittels der RegEx daraufhin überprüft, ob sie syntaktisch korrekte Mailadressen sind, um False Positives zu vermeiden.

Unser Programm ist nun zwar schon ein wenig umfangreicher als vorher, mit gerade mal 40 Zeilen Code aber immer noch sehr kompakt.

Wie bei der vorherigen Version wird auch dieses Mal wieder die Anzahl der gefundenen Mails und die Laufzeit des Programms am Ende ausgegeben:

Dieselbe Anzahl an Mails wird gefunden (129), jetzt allerdings in nur noch ca. 10% der Zeit (22 Sekunden statt 247). Wenn diese Geschwindigkeit gehalten werden kann, könnten wir mit diesem (immer noch sehr simplen!) Programm im Laufe von 24 Stunden bereits etwa 550.000 Emails „ernten“.

Python Programm

Die grundsätzliche Funktionalität unseres Email Harvesters ist hiermit demonstriert. Wer (natürlich nur für den privaten Gebrauch!) noch ein wenig daran arbeiten möchte, kann darüber nachdenken, die folgenden Dinge zu ergänzen:

  • Momentan wird nur die Anzahl der gefundenen Mailadressen ausgegeben, um tatsächlich Mails verschicken zu können, müssten die gefundenen Mails irgendwo gespeichert werden. Das kann ein einfaches Textfile sein oder eine Datenbank.
  • Momentan werden Links basierend auf dem mailto Attribut erkannt und mit einer RegEx verifiziert. Hier könnte man noch andere Möglichkeiten zur Emailerkennung ergänzen, beispielsweise eine RegEx um auch Emailadressen der Form: kontakt [ät] beispiel.de zu erkennen.
  • Momentan arbeitet das Programm eine vorgegebene Liste von Webseiten ab. Da wir aber sowieso schon alle Links aus dieser Seite extrahieren, könnten wir diesen Links genauso gut auch folgen und auf diese Weise neue Seiten entdecken.

 

Zudem benötigt unser Harvester natürlich eine Liste mit URLs als Input. Eine solche Liste zu finden, oder selbst zu erstellen, ist nicht weiter schwierig, wird dem Leser an dieser Stelle aber als Übung überlassen.

Was stellt man damit an?

Nun hat man also 550.000 Emails (nach einem Tag) bzw. 5,5 Millionen (nach 10 Tagen). Was für Schabernack kann man damit anstellen? Prinzipiell natürlich eine ganze Menge:

  • Malware (z.B. mit einer angehängten bösartigen Datei)
  • Phishing (z.B. durch einen Link der auf eine Seite verweist über die wir Zugangsdaten abfangen können)
  • Spam (z.B. „Kaufen Sie billiges Viagra“, „Helfen Sie diesem armen nigerianischen Prinz an sein Erbe zu kommen“, „Investieren Sie in diese neue Kryptowährung um Ihr Geld zu verfünfzigfachen“ etc.)

 

Da wir auf die Themen Malware und Phishing in weiteren Beiträgen unserer Email Serie noch näher eingehen werden, schauen wir uns an dieser Stelle das Geschäftsmodell des Spammers ein wenig näher an:

Spam

Gehen wir davon aus, dass unser Spammer die 550.000 gefundenen Mailadressen auch direkt verwenden wird, um in einer Mail für sein Produkt, was auch immer es ist, zu werben.

Wenn man von einer Antwortquote von 0,1% ausgeht (also jeder tausendste), sind das immerhin gute 550 Reaktionen, die ein Spammer pro Tag erwarten könnte. Angenommen jeder davon kauft für 10 Euro ein wertloses Produkt, macht das pro Tag bereits 5500 Euro. Wenn wir ein wenig pessimistischer sind und nur von 0,01% Antwortquote (also jeder zehntausendste) ausgehen, wären es immerhin noch 550 Euro. Dafür, dass der gesamte Prozess weitgehend automatisiert werden kann und somit wenig manuelle Interaktion erfordert, sicherlich kein schlechter Wert.

Wobei davon natürlich noch die Kosten für die Infrastruktur abgehen. Wer eine halbe Million Mails pro Tag verschicken will, kann das nicht über einen privaten Mail Account machen (bzw. bräuchte er dann sehr viele Accounts, da die meisten Anbieter die Zahl der gesendeten Mails limitieren, typischerweise auf einen Wert zwischen 500 und 5000 Mails pro Tag). Um die halbe Million Mails effizient verschicken zu können, bietet es sich also an, einen eigenen Mailserver aufzusetzen. Hier kann man sich natürlich beliebig austoben, je nachdem was einem alles wichtig ist. Als grobes Beispiel für die dabei entstehenden Kosten sei an dieser Stelle der Amazon Simple Email Service (SES) aufgeführt:

Gegenmaßnahmen

10 Cent pro 1000 Emails macht 55 Dollar pro Tag an „Versandkosten“ für eine halbe Million Mails. Also ungefähr 1% des erwarteten täglichen Gewinns (bei einer Reaktionsquote von 0,1%. Bei 0,01% betragen die Kosten 10% des erwarteten Gewinns). Diese Marge wird man sonst vermutlich nur in wenigen anderen Bereichen erreichen können.

Keine Links

Wie bereits gezeigt, ist eine Emailadresse standardmäßig eindeutig als solche im HTML Code der Webseite ersichtlich:

Das hat den schönen Vorteil, dass bei einem Klick auf den Link automatisch das Emailprogramm des Users geöffnet wird und die Kontakt Mail direkt in der Empfängerzeile steht:

Um ein linkbasiertes Auslesen der Mailadresse zu verhindern, kann man nun einfach diesen Link entfernen, d.h. die Emailadresse ist nicht mehr als Emailadresse ersichtlich, sondern nur als reiner Text:

Im weit verbreiteten CMS WordPress ist dies beispielsweise mit einem Klick auf „Link entfernen“ erledigt:

Anschließend wird die Emailadresse durch einen Linkbasierten Harvester nicht mehr gefunden.

Vorteil:

  • Die Emailadresse ist für einen User weiterhin klar als Email ersichtlich
  • Die Emailadresse kann kopiert und eingefügt werden, ohne dass weitere Veränderungen nötig wären

 

Nachteil:

  • Die Emailadresse kann durch einen RegEx basierten Harvester weiterhin problemlos ausgelesen werden

Diese Lösung bietet unseren Usern also weiterhin einen gewissen Komfort (auch wenn jetzt die Emailadresse kopiert und manuell in das Emailprogramm eingefügt werden muss), wird andererseits einen guten Harvester aber nicht stoppen können. Also besser als nichts, aber nicht perfekt.

Schreibweise ändern

Den Link zu entfernen verhindert, dass die Emailadresse durch den linkbasierten Harvester gefunden wird. Durch den regulären Ausdruck wird die Mail aber weiterhin gefunden, da sich nichts an ihrer Struktur geändert hat.

Um ein RegEx basiertes Auffinden der Mailadresse zu erschweren, muss die Schreibweise so abgeändert werden, dass sie durch die RegEx nicht mehr erfasst wird. Dabei muss allerdings darauf geachtet werden, dass die Mailadresse für einen regulären User weiterhin lesbar bleibt, zu große Veränderungen sind also kontraproduktiv.

Typischerweise findet man Verfremdungen in den folgenden Formen:

  • kontakt [ät] beispiel.de
    • @ Symbol durch [ät] ersetzt, Leerzeichen eingefügt
  • kontakt @ beispiel.de
    • Leerzeichen eingefügt
  • kontakt ät beispiel de
    • @ Symbol durch ät ersetzt, Punkt durch Leerzeichen ersetzt
  • kontakt(@)beispiel . de
    • @ Symbol durch (@) ersetzt, Leerzeichen vor und nach dem Punkt eingefügt

 

Allerdings haben alle diese Formen eines gemeinsam: Sie folgen einer bestimmten Struktur. Und das wiederum macht sie grundsätzlich mit einer RegEx auslesbar.

Zwar nicht mit derjenigen, die wir bisher verwendet haben (da diese keine Leerzeichen erfasst), allerdings wäre es kein Problem, eine neue RegEx zu definieren, die beispielsweise den zweiten Fall erfasst:

  • Vor dem @ können Buchstaben, Zahlen, bestimmte Sonderzeichen und nun auch Leerzeichen stehen
  • Dann kommt ein @ Symbol
  • Danach können wieder Buchstaben, Zahlen und bestimmte Sonderzeichen stehen, sowie Leerzeichen
  • Abschließend kommt noch der Punkt und die TLD
  • Für alle Strings, die wir auf diese Weise erfassen, können wir anschließend die Leerzeichen entfernen und haben dann wieder eine korrekte Emailadresse

 

Wenn man also eine gewisse Sicherheit haben möchte, dann muss man die Schreibweise so verunstalten, dass die ursprüngliche Struktur möglichst stark verzerrt wird. Beispielsweise durch unterschiedliche Zeichen (kontakt /ät? beispiel . de) oder eine unterschiedliche Anzahl von Leerzeichen (k o nt a kt   @be isp ie l. d   d).

Das wiederum hat den negativen Effekt, dass die Mail nicht nur automatisiert schwer zu verarbeiten ist, sondern auch von einem regulären User immer schwerer gelesen werden kann.

Als Walkaround könnte man beispielsweise auch die Mail über mehrere Zeilen aufteilen:

kontakt

@

beispiel

.de

Das ist noch einigermaßen gut lesbar (wenn auch sicher nicht optimal), kann aber nur schwer automatisiert verarbeitet werden.

Vorteil:

  • Wenn man es nicht zu sehr übertreibt, ist die Mail für einen regulären User gut lesbar und kann zudem kopiert werden (im Emailprogramm müssten dann beispielsweise nur die Leerzeichen entfernt werden, was einfacher ist als die komplette Mail von Hand abzutippen)

Nachteil:

  • Je nachdem wie weit man geht, ist die Mail auch für einen regulären User nur noch schwer zu lesen, bzw. werden eventuell wichtige Mails an eine nicht existierende Adresse versandt, was sich negativ auf den geschäftlichen Erfolg auswirken könnte.

 

Eine stark verfremdete Darstellung der Emailadresse bietet also durchaus einen guten Schutz vor RegEx basierten Email Harvestern, allerdings mit dem Nachteil, dass die Emailadresse von regulären Usern möglicherweise ebenfalls nicht mehr erkannt wird. Also eine Gratwanderung zwischen Security und Usability.

Als Bild einbinden

Da eine verfremdete Emailadresse zwar durchaus Sicherheit vor Harvestern bietet, allerdings oft nicht wirklich User freundlich ist, bietet sich eine dritte Möglichkeit als Kompromiss an: Die Einbindung der Emailadresse als Bild:

Dabei wird einfach ein Screenshot der Emailadresse angefertigt (z.B. mit dem Snipping Tool) und dieses Bild anschließend hochgeladen:

Die erste Emailadresse im Screenshot besteht aus Text, die zweite ist das eingefügte Bild. Wie zu sehen ist kaum ein Unterschied sichtbar. Abgesehen davon, dass die „Bildadresse“ leicht nach rechts verschoben ist, was aber durch eine Formatierung des Bildes leicht behoben werden könnte.

Obwohl das eingebundene Bild für einen User leicht lesbar ist, ist die Mailadresse im Sourcecode nicht als solche ersichtlich. Der nachfolgende Screenshot zeigt den HTML Code des obigen Screenshots, zunächst die Textemailadresse und dann die Bildemailadresse:

Vorteil:

  • Für einen User ist die Emailadresse problemlos lesbar
  • Die Adresse kann automatisiert aber nur schwer ausgelesen werden (zwar möglich durch Texterkennung in Bildern, allerdings sehr unwahrscheinlich, dass jemand auf diese Weise nach Emailadressen sucht, insbesondere, wenn diese nur für Spam gebraucht werden)

 

Nachteil:

  • Der User kann die Adresse nicht mehr kopieren, sondern muss sie abtippen. Kann bei komplexeren Adressen eventuell zu Frustration führen.

Zwar ist auch diese Maßnahme nicht perfekt, die Schnittmenge zwischen Userfreundlichkeit und Sicherheit vor Harvestern ist in diesem Fall aber am größten.

Fazit

Die wirklich perfekte Gegenmaßnahme gibt es also nicht, man kann es einem Spammer aber zumindest ein wenig schwerer machen an die eigene Emailadresse heranzukommen.

 

Weitere Titel aus unserer Serie "E-Mails als Waffe"