====== Authentifizierung ====== ++++Lernziele| * Was ist eine **Authentifizierung** in der Informatik und im wahren Leben? * Woher kommt der Name? * Welche **Methoden der Authentifizierung** gibt es in Informatik und im wahren Leben? * Analysiere die Sicherheit von **Passwörtern** zur Authentifizierung. * Sind (gute) Passwörter als alleiniges Authentifizierungsmittel sicher? * Welche Möglichkeiten haben Hacker, um an fremde Passwörter zu gelangen? * Mache Beispiele für gute und schlechte Passwörter. Warum sind sie gut/schlecht? Wie können Hacker vorgehen, um diese zu knacken? * Welche Massnahmen kann man im Bezug auf Passwörter treffen, um möglichst sicher zu sein? * Wie kann man herausfinden, ob man bereits Opfer von Hackern wurde? * Erklären, was Idee hinter **Brute-Force**-Attacke ist und verschiedene Versionen davon kennen. * Was sind die Stärken und Schwächen einer solchen Attacke? * Was ist eine **Drei-Faktor-Authentifizierung**? * Welche Faktoren gehören zu einer solchen? * Nenne für jeden Faktor mehrere Beispiele. * Wo macht eine Drei-Faktor-Authentifizierung besonders viel Sinn? * Was kann man selbst unternehmen, um möglichst sicher im Web unterwegs zu sein? * Analysiere eine Situation (Bsp. Geschichte mit sieben Geisslein) und gebe Tipps, wie man die Sicherheit erhöhen könnte. * **Programmieren:** * Brute-Force Attacke und ähnliche Codes **Programmieren** können. * Wissen, wie File eingelesen wird. ++++ * {{ :gf_informatik:web_sca:web_05_authentifizierung.pdf |Slides Authentifizierung}} * Märchen: [[https://www.grimmstories.com/de/grimm_maerchen/der_wolf_und_die_sieben_jungen_geisslein|Der Wolf und die sieben Geisslein]] ===== - Einführung ===== {{ :gf_informatik:authenticity.jpg?200|}} Ganz allgemein bedeutet //authentifizieren//: **zu prüfen, ob eine Behauptung zutrifft**. Zum Beispiel wird geprüft, ob ein Kunstwerk hinsichtlich der behaupteten Identität, des behaupteten Alters oder der behaupteten Herkunft //authentisch//, das heisst echt ist(1). Im Bereich der Computerwissenschaften – unserem Bereich – geht es fast immer um die **Prüfung der Identität oder Berechtigung einer Person**. {{:gf_informatik:wolf_und_sieben_geisslein.jpg?200 |}} Wie geht das? Wie prüfen wir, ob die Person "auf der anderen Seite" auch die ist, die sie zu sein behauptet? Diese Frage war auch für die sieben Geisslein im [[https://de.wikipedia.org/wiki/Der_Wolf_und_die_sieben_jungen_Gei%C3%9Flein|Märchen der Gebrüder Grimm]] relevant. Dass es sich bei dem Wesen hinter der Tür nicht um ihre Geissen-Mutter, sondern um den Wolf handelte, erkannten Sie zunächst an biometrischen Daten: Stimme und Pfoten-Farbe. Der einigermassen schlaue Wolf schaffte es aber, mit Täuschungsmanövern beide Prüfungen zu bestehen, sodass die Geisslein ihm die Türe öffneten. In der realen Welt, in der wir uns mit unseren Körpern begegnen, sind solche Täuschungen nicht so einfach: Menschen, die wir kennen, erkennen wir ziemlich gut an Stimme, Aussehen und Verhalten. Es wäre schwierig, jemandem glaubhaft zu machen, z. B. seine Schwester oder sein Bruder zu sein. Wenn wir uns aber als unbekannte Personen vorstellen, könnten wir leicht behaupten, jemand anderes zu sein. Deshalb ist es in manchen Situationen erforderlich, dass wir uns (zum Beispiel mit einer Identitätskarte) ausweisen: So kann die Behauptung "Ich bin X" authentifiziert werden. Auch in der virtuellen Welt, in der wir uns über Bildschirme und/oder Lautsprecher begegnen, werden Täuschungen einfacher. Vor allem dann, wenn keine Bilder oder Töne vorliegen. Woher weiss ich, dass die Person, mit der ich gerade im Chat schreibe, wirklich diese Person ist? Ob nicht jemand anderes gerade das Smartphone oder den Laptop am anderen Ende bedient? Auf vielen Webseiten und Plattformen reicht die Angabe eines korrekten Passworts, um zu "beweisen", dass man eine bestimmte Person oder ein bestimmter Benutzer ist (2). Wer es schafft, an mein Passwort zu kommen, kann auf der jeweiligen Webseite auf mein Benutzerkonto und alle dort vorhandenen Informationen zugreifen. **Eine Authentifizierung, die nur auf ein Passwort schaut, gilt daher als relativ unsicher.** Dazu mehr weiter unten. * (1) Jemand könnte mit einem Gemälde daher kommen und sagen: "Seht her: Dieses Bild ist von Vincent van Gogh!" – Nun gibt es einige Möglichkeiten, seine Behauptung zu prüfen. Wird festgestellt, dass das Bild tatsächlich (bzw. sehr wahrscheinlich) von Van Gogh ist, ist es als Van-Gogh-Bild authentifiziert. Vielleicht wird auch festgestellt, dass es bloss eine Kopie, nicht echt, nicht //authentisch// ist. * (2) ("Benutzer/Benutzerin" und "Person" meinen etwas völlig Unterschiedliches. Das wird auch dadurch klar, dass eine Person mehrere Benutzer sein kann und theoretisch für jedes Konto andere Namen und E-Mail-Adressen angeben könnte. Oft aber sind die Informationen, die zu einem Benutzer gespeichert sind, sehr zahlreich und deckungsgleich mit den Informationen über die Person, zu der das Benutzerkonto gehört.) ===== - Brute-Force Attacke ===== **Ziele:** * 'richtiges' Python installieren * Python-Module mit pip installieren können * Mit Brute Force Passwörter hacken In dieser Aufgabe geht es darum, **geheime Passwörter** mithilfe der Brute-Force Methode zu hacken, über welche man Zugriff auf **geheime Nachrichten** (Achtung: Flachwitz Alarm!) erhält. Insgesamt gibt es mind. fünf solcher Passwörter / Nachrichten, die man hacken kann. Beachte, dass alle Passwörter ausschliesslich die **Grossbuchstaben** `'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` verwenden. Es gibt also *keine* Kleinbuchstaben, Umlaute, Leerzeichen, Zahlen, Sonderzeichen, ... Für diese Aufgabe gibt es **zwei Versionen**: 1. **Online-Hack**: Hier wird eine Website gehackt, die auf einem Schulserver läuft. Achtung: Man hat nur Zugriff über das Netzwerk der Schule, also nicht von zuhause. 1. **Offline-Hack** Die (verschlüsselten) Daten, die gehackt werden sollen, werden auf den Computer heruntergeladen, es ist also kein Zugriff auf eine Website nötig. Daher kann man diesen Hack von überall aus machen. **Wähle eine der beiden Optionen** (online oder offline) und löse die Aufgaben weiter unten. Für jede Option gibt es ein Template mit vordefiniertem Code, den man verwenden soll. Lasse dich von diesem Code nicht einschüchtern: Du musst diesen nur anwenden aber *nicht verstehen*. ==== Templates für Hack ==== === Online (Website) === [[https://if.ksr.ch/sca/hackme/]] * Benötigt Python-Modul **Selenium**: `pip install selenium` * Benötigt aktuelle Version von **Google Chrome** * Erklärung: * Jedes Mal, wenn man auf der Website ein Passwort eingibt und den Button drückt, wird im JavaScript-File die Funktion `check_pw(...)` ausgeführt, die überprüft, ob das eingegebene Passwort korrekt ist oder nicht. Die Funktion gibt zwei Werte zurück: * Code: $201$ falls korrekt, $401$ falls falsch * Message * Der Code unten verbindet sich mit der Website und ruft die Funktion `check_pw(...)` auf und erhält den Code und die Message zurück. ++++Code| ### requires: `pip install selenium` ### DON'T CHANGE CODE FROM HERE ... from selenium import webdriver from selenium.webdriver.common.by import By # url to website url_website = "https://if.ksr.ch/sca/hackme/" # Open the webpage driver = webdriver.Chrome() driver.get(url_website) # Enter text and click button -> not relevant for our hack input_field = driver.find_element(By.ID,"textInput") # find the input box ... input_field.send_keys("guess pw here") # ... and insert text button = driver.find_element(By.ID,"btnSend") # find the button ... button.click() # ... and click it ### ... UNTIL HERE ### WRITE YOUR CODE BETWEEN HERE ... pw = "MY GUESS" # variable containing password code,message = driver.execute_script(f'return check_pw("{pw}")') # try password on website, returns code and message print(code,message) ### ... AND HERE. DON'T CHANGE LAST LINE: driver.quit() # Close the browser ++++ === Offline (verschlüsselte Daten) === * Benötigt Python-Modul **PyCryptoDome**: `pip install pycryptodome` * Erklärung: Die Python-Funktion `check_pw(...)` überprüft ein Passwort und erhält einen Code und eine Message (gleich wie bei Online-Version oben) zurück. ++++Code| ### requires: pip install pycryptodome ### DON'T CHANGE CODE FROM HERE ... from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad import hashlib encoding = 'utf-8' # 'latin-1' data_encrypted = [ { "pw_hashed" : "4ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260", "message_encrypted" : b'\xa5\x8a\xb6i\xfb\xe4\x1c\xeeN [\xcb\xb8\xe9\x85-' }, { "pw_hashed" : "ccc09a134cf88bae7be3f6d62cf24b9476a044c375a76d53b78eef18ea772f5f", "message_encrypted" : b'\x98I\x10\xb3\xbaW\x03V\x9e\x96;\xb0\xb2#\xc7\x04AA\xf4S\xf9H\x10\xf6\x9c\x8e\xd3jf\xfa\x17\xa1\xba\xb5\xae\xc5\n\xc0\xd4\xc8\x02,U\x10\xc2\xd62\xbe\xa6!l\x82\x82Hs\xde\xb7\x97\xf6\x0c\xa6\x85\xf2\xd0' }, { "pw_hashed" : "516a8d1c497179956af1feddc603960155d26aad82fa8c184dd27a14fc59da82", "message_encrypted" : b'\x89\xd55H\xb3\xab\x0b\x99\x19oW\x00\xfd\xc9*\xdc`\xb2\xb0N\xf7+m\xce\x8c\xf7\xd7k\xc5\x01\xec\xbf+f\x94\xd0\xb1\x04\xcd\xd2$Z\xf6\xdf\xee\xca\xa5V\xf6b\xce\n\x1f\xbc\x1c\xe4\x00zi\xe8:\xcb\x000' }, { "pw_hashed" : "1f40dc75353dade02cab2a64cc014d058bc16b3eec3b52b723dc1db5cfdc7875", "message_encrypted" : b'\x0c\xe0hb%\xe9E\xdb\x97\x10I\x17\xc2\xdbH4\x03\xf3M\xb20_\xa3\x13\xbd\x87\xd5\xe0\xc8\xcb\xab+\x89\r\x938@2\x0b.{t\x1a3\x85u\x14\xd3' }, { "pw_hashed" : "cb059e3e1d77a76665eaaeb7d289f54936ecb301a5ede2a0ac887c204b7bd4e4", "message_encrypted" : b'\x0fr\xbd~\x0b C\xd1\xdc\x83y\x0e\xf5Im\xf3U\x94\x7f\xd6\x8e\xde\xb6\xf5\x97\xf6\x06\x16\xd8o\xc4Q\x12[k%\xcf\xb2\x14\xea)Zi/e\x1buX?\xc4\x0e\xf9\\\xf9\xa5\xfb\x1e5\xecPi\xe8\x89Ty63`4\x89\x87\x08\x9b\xccj\xcd1y/\xc5\xdc#\x1fS\xa8\xe99\x07\x85\xda\xf5:\xd5' } ] def normalize_key(key): if len(key) < 16: key = key + (16-len(key)) * "a" elif len(key) < 64: key = key + (16-len(key)) * "a" else: key = key[:64] return key def encrypt(key: str, message: str): key = normalize_key(key).encode(encoding) cipher = AES.new(key, AES.MODE_ECB) # Using ECB mode padded_message = pad(message.encode(encoding), AES.block_size) # Pad message encrypted_message = cipher.encrypt(padded_message) # Encrypt the data return encrypted_message def decrypt(key: str, message: bytes): key = normalize_key(key).encode(encoding) cipher = AES.new(key, AES.MODE_ECB) # Using ECB mode decrypted_message = cipher.decrypt(message) decrypted_unpadded_message = unpad(decrypted_message, AES.block_size) return decrypted_unpadded_message.decode(encoding) # Decode bytes to string def hashme(s): return hashlib.sha256(s.encode(encoding)).hexdigest() def check_pw(pw): for data in data_encrypted: if hashme(pw) == data['pw_hashed']: return 201,decrypt(pw,data["message_encrypted"]) return 401,None ### ... UNTIL HERE ############################################## ### WRITE YOUR CODE BELOW: code, message = check_pw("WRONGPASSWORD") print(code) print(message) ++++ ==== Hilfe benötigt? ==== * [[gf_informatik:programmieren_ii_sca|Dossier Programmieren aus 1M]] * Verwende KI als Tutor (z.B. ChatGPT, Bing-Chat, ...) ==== Aufgabe 0 ==== **Ziel:** richtiges Python & VSCode einrichten 1. [[gf_informatik:python_vscode_setup_sca#setup_vscode_python|Richte Python & VSCode ein]] 1. Entscheide dich für eine Hack-Variante ("Online" oder "Offline") ... 1. ... und [[gf_informatik:python_vscode_setup_sca#python_module_installieren|installiere das benötigte Modul]] (siehe oben, welches Modul benötigt wird). 1. Optional aber empfohlen: Finde heraus, wie man [[gf_informatik:python_vscode_setup_sca#jupyter-notebooks_optional|Jupyter-Notebooks]] verwendent. Mit diesen kann man Code und Text miteinander kombinieren. ==== Aufgabe 1: Zufällige Zeichenkette ==== 1. Lade das passende Template oben herunter / kopiere es in ein Python oder Jupyter-Notebook File und führe es aus. 1. Finde das erste Passwort durch *ausprobieren* heraus: **Passwort 1**: ein einziger Grossbuchstabe 1. Schreibe nun den Code, der das zweite Passwort hackt: **Passwort 2**: drei zufällige Grossbuchstaben. Schreibe deinen eigenen Code, verwende keine Module wie itertools. ==== Aufgabe 2: Deutsches Wort ==== Das folgende Dokument enthält kapp $10000$ der am meisten verwendeten deutschen Wörtern: {{ :gf_informatik:web_sca:woerter_top10000de_upper.txt.zip |}} (muss zuerst *entzippt* werden!) 1. Finde heraus, wie man in Python ein **Text-File einliest** und Zeile für Zeile durchgeht. Verwende dazu **KI als Tutor**. 1. Hacke damit **Passwort 3:** Besteht aus einem Wort (nur Grossbuchstaben) aus der Liste oben. ==== Aufgabe 3 (optional) ==== Hacke die verbleibenden Passwörter: * **Passwort 4:** besteht aus mehr also drei zufälligen Grossbuchstaben. * Knacke Passwort 4 mithilfe einer **rekursiven Funktion**. Recherchiere selbst, was dies bedeutet. * **Passwort 5:** besteht auf zwei aneinandergereihten Wörtern aus der Liste von oben Andere Aufgaben: * Mache eine **Laufzeitanalyse**: Mithilfe des `time` Moduls (`import time`, kein pip nötig) kann man bestimmen, wie lange die Ausführung eines Codes dauert. Wie lange dauert es im schlechtesten Fall, um ein Passwort mit $1,2,3,4,5,\ldots$ Zufallszeichen (Grossbuchstaben) zu bestimmen? * Versuche, einen (oder beide) der **Codes**, die für diese Aufgaben zur Verfügung gestellt werden, zu **verstehen**. ===== - Multifaktor-Authentifizierung ===== Angenommen, du hast einen Gegenstand (z.B ein Tagebuch, ein Foto oder ein Superkräfte verleihender Trank), der **auf keinen Fall** in die Hände von jemand anderem gelangen darf. Du verschliesst den Gegenstand in einem bombensicheren Safe. Um den Safe zu öffnen, braucht es einen Pin Code. Was aber, wenn irgendjemand den Code herausfindet? Um die Sicherheit zu erhöhen, bringst du ein weiteres Schloss an, für das es einen Schlüssel braucht, den nur du hast. Was aber, wenn jemand heimlich eine Kopie deines Schlüssel anfertigt? Du erhöhst die Sicherheit nochmal: Ein weiteres Schloss mit Fingerabdruck-Scanner öffnet sich nur, wenn du deinen Daumen hinhältst. Dein Safe verfügt nun über eine Drei-Faktor-Authentifizierung. Zwar ist es auch möglich, eine Fingerabdruck-Überprüfung zu täuschen, aber es ist für jemanden ausser dir äusserst schwierig, alle drei Schlösser zu öffnen! Dieser jemand müsste etwas besonderes **wissen**, das nur du weisst: den Code. Und er müsste etwas besonderes **haben**, das nur du hast: den Schlüssel. Und er müsste etwas besonderes **sein**, das nur du bist: Der Mensch mit genau diesem Fingerabdruck. Das ist die Idee hinter einer Authentifizierung mit mehreren Faktoren: Es sollen Einzelheiten aus //unterschiedlichen Kategorien// geprüft werden: * **Wissensfaktoren** (knowledge factors) prüfen etwas, was der Benutzer weiss: Zum Beispiel ein Passwort oder ein Pin-Code. * **Besitzfaktoren** (ownership fators) prüfen, ob der Benutzer etwas hat: Zum Beispiel einen Schlüssel, ein bestimmtes Smartphone, eine Bank- oder Identitätskarte oder ein [[https://de.wikipedia.org/wiki/Security-Token|Security-Token]]. * **Inhärenzfaktoren** (inherence factors) prüfen etwas, das dem Benutzer inhärent (innewohnend, anhaftend) ist. Wir könnten auch sagen: etwas, was der Benutzer ist oder tut: Hierzu gehören biometrische Daten wie Fingerabdruck, Gesichtsmuster oder Stimme. Auch die eigene Unterschrift ist ein Inhärenzfaktor. Bei einer //Zwei-Faktor-Authentifizierung// (Two-factor authentication) werden Einzelheiten aus zwei dieser drei Kategorien geprüft. Der Ausdruck //Multi-factor authentication// lässt offen, ob zwei oder drei Faktoren erforderlich sind. Ein **entscheidender Vorteil der Mehrfaktor-Authentifzierung** im Internet besteht darin, dass //mehrere Anfgriffsvektoren// nötig sind, um ein Benutzerkonto zu knacken: * Es ist wohl einfach, ein einzelnes Token oder Mobiltelefon zu stehlen, aber schwierig, gleich 1000 oder mehr davon zu stehlen. Diese Art des Angriffs lässt sich also nicht leicht skalieren. * Dagegen ist es sehr einfach, ein Virus oder Keylogger auf tausenden von Geräten zu verbreiten oder eine Phishing-Mail an tausende von Benutzer:innen zu senden. Diese Art des Angriffs lässt sich gut skalieren. * Für die meisten Betrüger:innnen lohnt sich der Aufwand eines Angriffs erst dann, wenn damit gleich //mehrere// Benutzerkonten auf einmal geknackt werden können. === Aufgabe 1 – Prüfe und verbessere deine IT-Sicherheit === 1. **Analyse:** 1. Erstelle eine Liste aller Webseiten, die du (seltener oder öfter) besuchst und die eine Authentifizierung erfordern. 1. Überlege, bei wie vielen du die gleiche E-Mail-Adresse und das gleiche Passwort nutzt. 1. Du nutzt wohl auch Apps, die eine Authentifizierung verlangen, jedoch nur einmalig, bei jedem erneuten Öffnen ist keine neue Authentifizierung nötig. Was ist die Überlegung dahinter? Was wird vorausgesetzt? 1. **Schwachstellen schliessen:** 1. Überlegen, welche Lösung dir am sinnvollsten erscheint: Passwortmanager im Browser? Andere Passwortmanager? 1. Nötige Änderungen vornehmen: Zweifaktor-Authentifzierung aktivieren, evtl. PW-Manager installieren, evtl. einzelne Passwörter ändern. 1. Mindestens folgende Sicherheitsmassnahmen sollten umgesetzt werden: 1. Besonderes Passwort und 2FA beim E-Mail-Konto (Achtung: wahrscheinlich muss ein Key ausgedruckt werden, der unbedingt aufbewahrt werden muss). 1. Laptop und Smartphone mit Passwort/Fingerabdruck o.ä. gesperrt. ===== Lösungen ===== ++++Brute-Force| ### requires: `pip install selenium` ### DON'T CHANGE CODE FROM HERE ... from selenium import webdriver from selenium.webdriver.common.by import By # url to website url_website = "https://if.ksr.ch/sca/hackme/" # Open the webpage driver = webdriver.Chrome() driver.get(url_website) # Enter text and click button -> not relevant for our hack input_field = driver.find_element(By.ID,"textInput") # find the input box ... input_field.send_keys("guess pw here") # ... and insert text button = driver.find_element(By.ID,"btnSend") # find the button ... button.click() # ... and click it ### ... UNTIL HERE ### WRITE YOUR CODE BETWEEN HERE ... alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ## PASSWORD 1 print("PASSWORD 1") for pw in alphabet: code,message = driver.execute_script(f'return check_pw("{pw}")') # try password on website, returns code and message if code == 201: print(pw) print(message) ## PASSWORD 2 print("PASSWORD 2") for x in alphabet: for y in alphabet: for z in alphabet: pw = x + y + z code,message = driver.execute_script(f'return check_pw("{pw}")') # try password on website, returns code and message if code == 201: print(pw) print(message) ## PASSWORD 3 print("PASSWORD 3") with open("woerter_top10000de_upper.txt",'r') as file: for line in file: pw = line.strip() # strip entfernt Leerschläge und Zeilenumbrüche am Anfang und Ende code,message = driver.execute_script(f'return check_pw("{pw}")') # try password on website, returns code and message if code == 201: print(pw) print(message) ### ... AND HERE. DON'T CHANGE LAST LINE: driver.quit() # Close the browser ++++