Einen Webcrawler in Python programmieren

https://bildung.social/@oerinformatik/110451036309748716

https://oer-informatik.de/python_webcrawler

tl/dr; (ca. 10 min Lesezeit): Es soll ein Webcrawler programmiert werden, der den eigenen Internetauftritt nach dort veröffentlichten E-Mail-Adressen durchsucht. Für die betroffenen Besitzer der E-Mail-Konten sollen so Awareness-Trainings angeboten werden. (Zuletzt geändert am 30.05.2023)

Social Engineering bei SPAM und Ransomware

Social engineering-Angriffe nutzen Neugierde und vermeintliche Vertrauensstellungen, um sich Zugang zu Systemen zu verschaffen. Ein vor der Bürotür ausgelegter USB-Stick erweckt Neugierde: Was mag darauf sein? Es besteht eine gewisse Chance, dass die Neugierde größer ist als die Vorsicht - und wider besseren Wissens der Stick eingesteckt wird.

Ein irgendwie entsetzter Roboter neben einem Serverschrank. Offensichtlich ist etwas schreckliches passiert…
Ein irgendwie entsetzter Roboter neben einem Serverschrank. Offensichtlich ist etwas schreckliches passiert…

Ein anderer Angriffsvektor ist das Vorgaukeln von Vertrauensstellungen. Bei einer Mail, deren Absender vermeintlich eine Kollegin oder ein Kollege ist, ist die Chance größer, dass ein Anhang geöffnet wird, ein gesendetes Archiv entpackt oder Makros ausgeführt werden. Auf diesem Weg findet Schadcode seinen Weg in Unternehmensnetze. Auch Ransomware wie der Erpressungstrojaner Locky nutzt derartige Einfallstore als ersten Schritt.

Dazu werden durch die Angreifer jedoch Informationen benötigt, die beispielsweise auch öffentlich auf der Internetseite des eigenen Unternehmens preisgegeben werden: wenn auf der Internetseite zwei Namen (oder gar zwei E-Mail-Adressen) veröffentlicht sind, die miteinander in Bezug stehen, ist die Wahrscheinlichkeit groß, dass eine Mail des einen Kontos vom anderen Konto geöffnet wird - und zwar ohne die Vorsichtsmaßnahmen, die bei unbekannten Absendern greifen würden.

Der Versuch von DALL-E, einen Datenklau am PC darzustellen (einer greift einem Computernutzer über die Schultern in die Tastatur)
Der Versuch von DALL-E, einen Datenklau am PC darzustellen (einer greift einem Computernutzer über die Schultern in die Tastatur)

Webcrawler zur Analyse des E-Mail-Harvesting

Hier soll der Webcrawler bei der Gefährdungsbeurteilung helfen: Analysiert werden soll die Anfälligkeit des Unternehmensauftritts im Internet für das gezielte automatisierte Sammeln von E-Mail-Adressen, die miteinander in Kontakt stehen (E-Mail-Harvesting).

Hierzu soll ein Python-Tool entwickelt werden. Dieses Tool soll alle E-Mail-Adressen, die auf den Internetseiten eines Unternehmens veröffentlicht werden, auflisten.

Dieser Webcrawler soll

  • nach Eingabe einer Start-URL selbständig die E-Mail-Adressen auf der jeweiligen Seite finden,

  • in einer zweiten Iteration alle direkt verlinkten Seiten einer Domain untersuchen,

  • in einer dritten Iteration alle verlinkten Seiten der Domain bis zu einer einzugebenden Tiefe an Ebenen durchsuchen.

Dabei soll er zu jeder gefundenen E-Mail-Adresse alle URLs, auf denen sie gefunden wurde, speichern.

Das Programm soll zwei Berichte als Textdatei ins Dateisystem ausgeben können:

  • die gefundenen E-Mail-Adressen alphabetisch sortiert mit zugehörigen Links und

  • die gefundenen E-Mail-Adressen und deren Häufigkeit entsprechend der Häufigkeit.

Bericht 1:

anton.mustermann@beispieldomain.de
 - http://www.beispieldomain.de/hierauch
 - http://www.beispieldomain.de/hierauchnochmal
musterfrau@beispieldomain.de
 - http://www.beispieldomain.de/hier
 - http://www.beispieldomain.de/hierauch
 - http://www.beispieldomain.de/hierauch

Bericht 2:

musterfrau@beispieldomain.de (3)
anton.mustermann@beispieldomain.de (2)

Es soll sichergestellt werden, dass jede Seite nur einmal untersucht wird.

Mithilfe der so gewonnenen Liste soll später die Unternehmensleitung entscheiden können, ob die betroffenen Adressen veröffentlicht werden müssen und ob weitere Maßnahmen (Sensibilisierung der Mitarbeiter / Kunden, E-Mail-Empfang in isolierten Netzwerken) erforderlich sind.

Ein Roboter liest ein Buch. Eigentlich soll es der Webcrawler sein, aber DALL-E hat mich nicht verstanden…
Ein Roboter liest ein Buch. Eigentlich soll es der Webcrawler sein, aber DALL-E hat mich nicht verstanden…

Disclaimer

Webcrawler produzieren Traffic, verarbeiten und speichern Daten, produzieren letztlich CO_2. Sie sollten also nicht aus Jux und Dollerei ohne konkreten Anlass laufen.

Wenn Webcrawler systematisch Internetseiten durchsuchen, öffnen sie alle Unterseiten einer Webpage. Sie verhalten sich wie ein Clickmonkey, der wild auf alles klickt, was sich auf der Seite befindet. Das kann zweierlei folgen haben:

Ein Affe an einer Tastatur. Der Clickmonkey klickt auf alles, was ihm in den Weg kommt.
Ein Affe an einer Tastatur. Der Clickmonkey klickt auf alles, was ihm in den Weg kommt.
  • Das htt-Protokoll sieht vor, dass GET-Aufrufe (das sind Klicks auf Links in der Regel) keinerlei Seiteneffekte haben dürfen. Sie müssen also safe sein. Gegen diese Protokollregel könnten Programmierer aber auch verstoßen haben und ggf. Aktionen wie “Lösche alle Kundendaten” mit einem GET-Request auslösen. Zugegeben: Ein unrealistisches drastisches Beispiel, aber eben nicht unmöglich. Wenn derartig großzügig ausgelegte Standards im Unternehmen vorkommen können, sollte man den Crawler nicht auf die “echte” Seite loslassen.

  • Webcrawler verursachen Traffic auf dem Server, werden im Serverlog registriert und von Tools gegebenenfalls als verdächtiges Verhalten interpretiert. Manche Admins stufen Crawler als unerwünschten Traffic ein und sperren den Zugang der Crawler (z.B. über dessen IP-Adresse). Gegebenenfalls ist dann der Webauftritt von diesem Rechner oder aus diesem Subnetz nicht mehr erreichbar.

Webauftritte enthalten in der Regel eine robots.txt-Datei, in der festgeschrieben ist, wer (“User-Agent”) welche Verzeichnisse durchsuchen darf. Das Auswerten dieser Datei belassen wir zunächst den Fortgeschrittenen. Damit wir die Regeln der jeweiligen robots.txt nicht brechen, habe ich unter https://oer-informatik.gitlab.io/python-basics/webcrawler/design15/index.html eine kleine Internetseite aus einem Template erstellt, ein paar Unterseiten und viele Mailadressen hinterlegt. Diese Adresse kann als Ausgangspunkt für erste Gehversuche dienen.

Ausgangspunkt: Codebeispiel

Ausgangspunkt der Entwicklung kann das folgende Stück Code sein. Mithilfe der Bibliothek requests (ggf. per python -m pip install requests nachladen) wird der HTML-Quelltext von Webpages ausgelesen.

Die Bibliothek re wiederum sorgt mit Regular Expressions dafür, dass bestimmte Muster erkannt werden (E-Mail-Adressen, Links zu Unterseiten). Der Ausdruck [a-z]+@[a-z]+ soll ein Ausgangspunkt dafür sein, E-Mail-Adressen im HTML-Quelltext zu finden. Natürlich funktioniert das Programm noch nicht korrekt, stellt aber die Techniken vor, die wir benötigen:

Realisierung

Die Entwicklung soll in 3 Iterationsschritten ablaufen: zum jeweiligen Unterrichtsende sollen jeweils Prototypen vorliegen, die bereits einen (selbstgewählten) Teil des Funktionsumfangs umsetzen.

  1. Gliedert den Programmablauf zunächst, in dem ihr Klassen und Methoden definieren, die bestimmte Aufgaben (Operations) des Webcrawlers übernehmen. Ruft diese Methoden als Abfolgen in einer Methode (Integration) auf, ohne die einzelnen Methoden bereits implementiert zu haben (siehe Integration Operation Segregation Principle (IOSP)).

  2. Erstellt einfache Tests für diese Methoden mit pytest

  3. Dokumentiert das Projekt in ihrem git-Repository mit einer Aussagekräftigen Readme-Datei

  4. Erweiterung 1: Sofern die oben genannten Anforderungen bereits umgesetzt wurden ergänzt eine Ausnahmen- und Fehlerbehandlung in das Programm.

  5. Erweiterung 2: Webauftritte regeln mit einer robots.txt-Datei in der Regel, welche Bereiche von Crawler durchsucht werden dürfen. Informiert euch über diesen Mechanismus (z.B. über die entsprechende Seite von SelfHTML) und berücksichtigt die Informationen beim Crawling. Wie kann ich eingeben, als welcher UserAgent mein Browser auftritt?

  6. Erweiterung 3: Gegebenenfalls müssen viele Unterseiten überprüft werden und es muss lange auf die Antwort der Anfragen gewartet werden. Informiert euch zu Parallelisierung in Python. Wie kann realisiert werden, dass nur eine feste Anzahl an Threads gleichzeitig arbeitet?

index.html - martina.mustermann@beispieldomain.de - !#$%&’*+-/=?^_`.{|}~@example.com - admin@[192.168.102.10] - michaela-mustermann@beispieldomain.de - hans-peter.richter@anwalt.beispielagentur.info - farbenschubser@beispiel-agentur.de 1-unterseite.html - x@example.com - example-indeed@strange-example.com - “john..doe”@example.org 1-1-unterseite (alles von 1-unterseite und zusätzlich:) - fully-qualified-domain@example.com - dmin@mailserver1 - user.name+tag+sorting@example.com 1-2-unterseite (alles von 1-unterseite und zusätzlich:) - user-@example.org - disposable.style.email.with+symbol@example.com 1-3-unterseite (alles von 1-unterseite und zusätzlich:) - martina.mustermann@beispieldomain.de’> 2-unterseite.html - 2-kontakt.html 3-impressum.html

Ausgangspunkte zur weiteren Recherche:

  • Was sind gültige E-Mail-Adressen? Das Dokument “Request for comments 5322” legt in Abschnitt 3.4.1 fest, aus welchen Bestandteilen eine E-Mail-Adresse besteht und schlüsselt in Abschnitt 3.2.3 den Aufbau der Bestandteile auf.

  • Wie erstelle ich Reguläre Ausdrücke?


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: Einen Webcrawler in Python programmieren” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/python_webcrawler veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/python-basics/webcrawler. Stand: 30.05.2023.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: