© jamesteohart

Authentifizierung mit 802.1X Zertifikaten & Windows Server 2016

Dieser Beitrag zeigt, wie ein Netzwerk mit Hilfe von Zertifikaten, sowie 802.1X in einer Microsoft Windows Server 2016 Domäne gesichert werden kann. Das Protokoll 802.1X ermöglicht es, eine Authentifizierung eines Hosts bei Verbindungsherstellung mit einer Netzwerkkomponenten, etwa einem Switch, zu erzwingen. Auf Basis eines Regelwerks kann so beispielsweise realisiert werden, bestimmten Hosts oder gar Nutzern den Zugriff auf das Netzwerk zu erlauben oder zu verbieten bzw. diesen verschiedenen VLANs im Netzwerk zuzuordnen.

Beispielkonfiguration - Aufbau des 802.1X Labs

Die folgende Topologie besteht aus dem Mindestumfang zur Demonstration von 802.1X. Im Detail werden drei Komponenten verwendet:

  • Ein Microsoft Windows 7 Notebook als aufzunehmenden Client,
  • ein Microsoft Windows Server 2016 Host, sowie
  • ein Switch, im Beispiel ein Cisco Catalyst 3560-CG PoE.

Die Vorgehensweise bei Microsoft Windows Server 2012, sowie Windows 8 oder Windows 10 als Client ist vergleichbar. Um reproduzierbare Ergebnisse zu erhalten, verwende ich für die Demonstration eine neue, bisher ungenutzte Windows 7 sowie Windows Server 2016 Installation.

Microsoft Windows Server 2016 - Neue Installation

Microsoft Windows Server 2016 - Neue Installation

Microsoft Windows 7 - Neue Installation

Microsoft Windows 7 - Neue Installation

Es folgt die Konfiguration der Netzwerkkomponente, im Beispiel dem Switch. Die folgende Konfiguration dient einer ersten Prüfung, ob alle Geräte im Netzwerk korrekt miteinander verbunden wurden sowie miteinander kommunizieren können.

Initiale Netzwerkkonfiguration

Der Server und das Notebook sind direkt an einen Cisco-Switch angeschlossen. Das Windows 7 Notebook ist mit dem Anschluss Gi0/1, der Windows Server 2012 mit dem Anschluss Gi0/2 des Switch verbunden. Im Lab werde ich das VLAN 20 als Produktiv-VLAN verwenden.

Die initiale Konfiguration des Switch ist wie folgt:

# VLAN 20 anlegen
Switch(config)#vlan 20
Switch(config-vlan)#name Productive
Switch(config-vlan)#exit

# Interface Gi 0/1 als Access-Port im VLAN 20
Switch(config)#int gi 0/1
Switch(config-if)#sw mo ac
Switch(config-if)#sw ac vl 20

# Interface Gi 0/2 als Access-Port im VLAN 20
Switch(config)#int gi 0/2
Switch(config-if)#sw mo ac
Switch(config-if)#sw ac vl 20

# SVI Interface im VLAN 20 anlegen
Switch(config)#int vlan 20
Switch(config-if)#ip address 172.16.0.100 255.255.255.0
Switch(config-if)#no shut

Die Konfiguration verschiebt beide Windows-Hosts in das VLAN 20. Der Switch selbst ist ebenfalls im VLAN 20 unter der IP 172.16.0.100 erreichbar. Im nächsten Schritt werden IP Adressen für die Netzwerkkonnektivität vergeben, beginnend auf dem Windows Server, mit der Adresse 172.16.0.1/24.

Microsoft Windows Server 2016 - IP-Konfiguration Netzwerkadapter

Microsoft Windows Server 2016 - IP-Konfiguration Netzwerkadapter

Der Eintrag eines Gateways ist für unsere Beispieltopologie nicht notwendig, da sich alle Geräte innerhalb eines Subnetzes befinden.
Weiterlesen

© shaiith - Fotolia.com

Timing-Angriffe und deren Auswirkungen

Bei einem Timing-Angriff ("Timing Attack") handelt es sich um eine Form eines Seitenkanalangriffs auf eine bestimmte Implementierung in Hard- oder Software. Die Möglichkeit eines Timing-Angriffs kann selbst bei einfachsten Entwicklungen zu erheblichen Auswirkungen auf die Sicherheit eines Systems führen.

Was ist ein Timing-Angriff?

Bei einem Timing-Angriff werden statistische Verfahren genutzt, um Unterschiede in der Zeitdauer einer bestimmten Operation zu erfahren. Es wird also beispielsweise gemessen, wie lange ein Webserver braucht, um auf eine Loginanfrage zu reagieren. Sollten sich bei den Messungen bestimmte Muster feststellen lassen, so könnten aus diesen Informationen extrahiert werden, die eigentlich geheim gehalten werden sollten. Klingt recht kompliziert, lässt sich aber anhand eines einfachen Beispiels recht eindrucksvoll demonstrieren.

In meinem Github Repository habe ich unter anderem ein in PHP geschriebenes Loginsystem hinterlegt. Der eigentliche, serverseitige Login wird von der Datei "do-login.php" ausgeführt. Im folgenden Beispiel habe ich den Code zur Demonstration etwas modifiziert und auf das wesentliche reduziert:

<?php

// Username & Password als Variable speichern
$username = $_POST['username'];
$password = $_POST['password'];

// Datenbankabfrage des Usernamens
$query = "SELECT * FROM users WHERE username='" .  $_POST['username'] . "'";
$result = mysql_query($query);

// Wenn der Username existiert, dann ...
if (mysql_num_rows($result) == 1)
{ 

	// Speicher den Datensatz des Users in $row
	$row = mysql_fetch_assoc($result);
 
	// Generiere einen Hash des Userpassworts	
	$hash = password_hash($password);

	// Vergleiche Hash mit gespeichertem Hash
	if ( $hash == $row['password'] )
	{
		echo "Authentication successfully.";
	}
	else
	{
		echo "Authentication failed.";
	}
}
// Es existiert kein User mit dem Usernamen
else
{
	echo "Authentication failed.";
}

?>

Zum Login in eine Anwendung bzw. auf einer Webseite wird ein Code wie oberer nahezu als Standard eingesetzt. Schlecht ist er auf dem ersten Blick nicht:

  • Es ist für den Benutzer nicht ersichtlich, ob ein Username existiert. Er bekommt auch bei einem nicht existenten Usernamen stets die Meldung "Authentication failed" zurück.
  • Der Code ist aufgeräumt, auf das wesentliche reduziert. Der Hash wird erst berechnet, wenn der User auch tatsächlich existiert, was effizient ist.
  • Die SQL Abfrage wurde einfach gehalten, um Fehler durch Komplexität zu vermeiden.

Bei genauerem Hinsehen hat der Code jedoch einige erhebliche Schwachstellen.

Schwachstellen

Wer sich etwas mit PHP auskennt, kann versuchen, die Probleme im Quellcode vor dem Weiterlesen des Textes zu identifizieren.

Weiterlesen

© peshkova - Fotolia.com

HTTPs: Unverzichtbar in der heutigen Zeit

Sobald Passwörter zum Login für Webseiten verwendet werden, ist HTTPs unverzichtbar. Im Folgenden möchte ich aufzeigen, warum dem so ist! Ich beginne mit einer Übersicht der gängigsten Authentifizierungen für Web-Portale.

(1) Klartext Login

Die einfachste Variante: Der Login im Klartext.

Account anlegen

Der Benutzername und das Passwort werden im Klartext an den Server gesendet.

Plaintext Registration

Plaintext Registration

Anmeldung

Zur Anmeldung wird der Benutzername und das Passwort im Klartext an den Server gesendet.

Plaintext Login

Plaintext Login

Sicherheit

Die folgende Analyse wertet die Sicherheit des Verfahrens aus. Die Liste ist ein Auszug einiger wichtiger Sicherheitsparameter, jedoch nicht abschließend.

Klartextpasswort geschütztNein
Replay-Angriff verhindertNein. Wird das Passwort während der Anmeldung mitgeschnitten, kann dieses zum Login genutzt werden.
Login nach Kompromittierung der Datenbank verhindertNein. Das in der Datenbank gespeicherte Passwort kann zum Login verwendet werden.
Man-in-the-Middle verhindertNein. Es gibt keine Möglichkeit sicherzustellen, dass der Client direkt mit dem Server kommuniziert.

Fazit: Erhebliche Risiken; bietet über unverschlüsselte Kommunikationskanäle keinerlei Sicherheit.

Weiterlesen

© buchachon - Fotolia.com

Sicherer Web-Login mit bCrypt und Javascript

User verwenden auf verschiedenen Webseiten häufig gleiche und meist auch schwache Passwörter. Die wenigsten Nutzer im Internet sind technisch so versiert, ausreichende sichere Passwörter generieren und nutzen zu können. Vielfach fehlt ein grundlegendes Basiswissen aus dem Bereich der IT-Sicherheit.

Dies ist aus mehreren Grunde problematisch, denn es kann nicht sichergestellt werden,

  • dass der Anbieter Passwörter angemessen schützt,
  • Passwörter durch den Anbieter nicht weitergegeben werden, oder
  • das Passwörter während der Übertragung an den Webserver nicht mitgeschnitten werden, hierbei ist auch https keine Garantie.

Um die Daten des Users bestmöglich zu schützen, sind an dieser Stelle in erster Linie die Anbieter und Entwickler in der Pflicht. Das Verhalten der Benutzer wird sich auf absehbare Zeit nicht ändern.

Clientseitige Implementierung

Eine Möglichkeit, dass Problem zu mindern, besteht darin, Passwörter zu keiner Zeit unverschlüsselt zu übertragen. Einwegfunktionen zur Sicherung von Passwörtern sollten bereits im Browser des Clients ausgeführt werden.

--> Das komplette Code-Beispiel findet sich auf Github!

Der heutigen Beitrag zeigt eine Beispielimplementierung auf Basis von javascript-bcrypt. Passwörter werden als salted bCrypt-Hash gespeichert.

Das Beispiel ist lediglich ein Ansatz und an vielen Stellen noch nicht ausgereift. Fehlerzustände werden z.B. teilweise noch nicht korrekt behandelt oder Brute-Force Angriffe noch nicht migriert. Das Skript stellt lediglich eine Arbeitsgrundlage zur Weiterentwicklung dar.

Passwort setzen/ ändern

Das Passwort wird mit bCrypt und einem zufälligen Salt verarbeitet und anschließend an den Webserver übertragen. Der Webserver speichert den Hash zusammen mit dem Benutzernamen. Der Anbieter hat zu keiner Zeit das Klartextpasswort erhalten.

Zusammenfassung:

  • Hash erstellen
  • Hash an Server übertragen

Passwort verifizieren

Auch bei der Verifikation darf das Passwort nicht im Klartext übermittelt werden. Hierbei ergibt sich jedoch die Schwierigkeit, dass der Salt für jeden Nutzer unterschiedlich ist und somit das Passwort nicht einfach erneut als Hash übertragen werden kann. Aus diesem Grund muss beim Login der Salt des Users an die Login-Form übertragen werden.

Zusammenfassung:

  • Username eingeben
  • Salt vom Server für Usernamen abholen
  • Passwort eingeben
  • Hash erstellen
  • Hash an Server übertragen, dort Abgleich

Weiterlesen

© timkaekler - Fotolia.com

PHP Anwendungen absichern

Nachdem ich vor knapp 3 Wochen zufällig festgestellt habe, dass über das PHP-Webinterface von einem der größten deutschen Web-Hoster nahezu alle Rechnungen, unter anderem inkl. Kunden-Adressen, gekürzten Bankverbindungen, Domains sowie IP-Adressen öffentlich abrufbar sind, habe ich mich entschieden, einen kurzen Beitrag über die Absicherung von Web-Anwendungen zu schreiben. Zur Ausnutzung der Lücke war keinerlei technisches Fachwissen erforderlich - das Skript zum Download der Rechnung hat einfach jede beliebige Rechnung ungeprüft ausgeben. In der URL musste nur die gewünschte Rechnungsnummer eingegeben werden. Aufgefallen ist es mir, nachdem ich bemerkt hatte, dass ich eine Rechnung von meinem Zweitaccount beim Anbieter herunterladen konnte, ohne dass ich dort noch angemeldet war.

Problem 1: Keine Authentifizierung

Oftmals finde ich Anwendungen, die zwar einen Login haben, dieser jedoch nur den Zweck hat, auf einen geschützten Bereich weiterzuleiten. Beim Öffnen einer Seite in einem geschützten Bereich wird nicht erneut geprüft, ob der User authentifiziert ist. Dabei lässt sich dies unglaublich leicht realisieren:

<?php
session_start();
 
if (isset($_SESSION['username'])) {
   --> Passt
} else {
   --> Zur Anmeldung weiterleiten
}
?>

Geschützter Content sollte niemals (!) ohne Authentifizierung ausgeführt werden.

Problem 2: Keine Autorisierung

Neben der Authentifizierung sollte stets geprüft werden, ob der User auch autorisiert ist, die gewünschte Aktion auszuführen. Im Beispiel einer Rechnungsabfrage über SQL darf niemals die Anfrage ungeprüft über SQL ausgeführt werden. Die SQL Anfrage sollte soweit eingeschränkt sein, dass ein User nur auf Daten zugreifen kann, die für ihn bestimmt sind.

Problem 3: Unverschlüsselte Übertragung

Ein geschützter Bereich bringt wenig, wenn die Anmeldung im Klartext durchgeführt wird. Es kann nur in den seltensten Fällen sichergestellt werden, dass die Daten unterwegs nicht ausgelesen werden können. Einen HTTP Request mit Wireshark auszulesen, bedarf keines großen Könnens. Die Thematik wird umso schwerwiegender, wenn im Unternehmen Single-Sign-On (SSO) bzw. LDAP verwendet wird.

Weiterlesen

Martin Witkowski zu Themen aus IT, Datenschutz & Sicherheit.