Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Die Entwicklung einer sicheren Netzwerkinfrastruktur auf hoher Ebene ist für die meisten Netzwerkanwendungsentwickler eine Priorität. Die Socketsicherheit wird jedoch häufig übersehen, obwohl es bei der Prüfung einer vollständig sicheren Lösung sehr wichtig ist. Die Socketsicherheit behandelt insbesondere Prozesse, die an denselben Port gebunden sind, der zuvor von einem anderen Anwendungsprozess gebunden wurde. In der Vergangenheit war es möglich, dass eine Netzwerkanwendung den Port einer anderen Anwendung "entführert", die leicht zu einem "Denial of Service"-Angriff oder Datendiebstahl führen konnte.
Im Allgemeinen gilt die Socketsicherheit für serverseitige Prozesse. Genauer gesagt gilt socketsicherheit für jede Netzwerkanwendung, die Verbindungen akzeptiert und IP-Datagrammdatenverkehr empfängt. Diese Anwendungen binden in der Regel an einen bekannten Port und sind häufige Ziele für böswilligen Netzwerkcode.
Clientanwendungen sind weniger wahrscheinlich die Ziele solcher Angriffe – nicht weil sie weniger anfällig sind, sondern weil die meisten Clients an lokale "flüchtige" Ports anstatt an statische "Dienstports" binden. Clientnetzwerkanwendungen sollten immer an kurzlebige Ports gebunden sein (durch Angabe von Port 0 in der SOCKADDR-Struktur, auf die der Parameter name beim Aufruf der Funktion bind verweist), es sei denn, es gibt einen überzeugenden architektonischen Grund, der dagegen spricht. Die ephemeren lokalen Ports bestehen aus Ports, die größer als Port 49151 sind. Die meisten Serveranwendungen für dedizierte Dienste binden an einen bekannten reservierten Port, der kleiner oder gleich Port 49151 ist. Für die meisten Anwendungen gibt es in der Regel keinen Konflikt für Bindungsanforderungen zwischen Client- und Serveranwendungen.
In diesem Abschnitt werden die Standardsicherheitsstufe auf verschiedenen Microsoft Windows-Plattformen und die Auswirkungen der spezifischen Socketoptionen SO_REUSEADDR und SO_EXCLUSIVEADDRUSE auf die Netzwerkanwendungssicherheit beschrieben. Ein zusätzliches Feature, das als erweiterte Socketsicherheit bezeichnet wird, ist unter Windows Server 2003 und höher verfügbar. Die Verfügbarkeit dieser Socketoptionen und der erweiterten Socketsicherheit variiert je nach Version von Microsoft-Betriebssystemen, wie in der nachstehenden Tabelle dargestellt.
Plattform | SO_REUSEADDR | SO_EXCLUSIVEADDRUSE | Erweiterte Socketsicherheit |
---|---|---|---|
Windows 95 | Verfügbar | Nicht verfügbar | Nicht verfügbar |
Windows 98 | Verfügbar | Nicht verfügbar | Nicht verfügbar |
Windows Me | Verfügbar | Nicht verfügbar | Nicht verfügbar |
Windows NT 4.0 | Verfügbar | Verfügbar in Service Pack 4 und höher | Nicht verfügbar |
Windows 2000 | Verfügbar | Verfügbar | Nicht verfügbar |
Windows XP | Verfügbar | Verfügbar | Nicht verfügbar |
Windows Server 2003 | Verfügbar | Verfügbar | Verfügbar |
Windows Vista | Verfügbar | Verfügbar | Verfügbar |
Windows Server 2008 | Verfügbar | Verfügbar | Verfügbar |
Windows 7 und höher | Verfügbar | Verfügbar | Verfügbar |
Verwenden von SO_REUSEADDR
Die SO_REUSEADDR Socket-Option ermöglicht es einem Socket, einen Port zwangsweise zu belegen, der von einem anderen Socket verwendet wird. Der zweite Socket ruft setsockopt auf, wobei der optname-Parameter auf SO_REUSEADDR gesetzt ist und der optval-Parameter auf einen booleschen Wert von TRUE gesetzt ist, bevor bind am selben Port wie der ursprüngliche Socket aufgerufen wird. Sobald der zweite Socket erfolgreich gebunden wurde, ist das Verhalten für alle an diesen Port gebundenen Sockets unbestimmt. Wenn beispielsweise alle Sockets auf demselben Port den TCP-Dienst bereitstellen, kann nicht garantiert werden, dass eingehende TCP-Verbindungsanforderungen von dem richtigen Socket über diesen Port verarbeitet werden. Das Verhalten ist nicht deterministisch. Ein bösartiges Programm kann SO_REUSEADDR verwenden, um Sockets, die bereits für Standardnetzwerkprotokolldienste verwendet werden, zu binden, um den Zugriff auf diesen Dienst zu verweigern. Für diese Option sind keine speziellen Berechtigungen erforderlich.
Wenn eine Clientanwendung an einen Port gebunden wird, bevor eine Serveranwendung eine Bindung an denselben Port herstellen kann, können Probleme auftreten. Wenn die Serveranwendung mithilfe der Socketoption SO_REUSEADDR erzwingt, sich an denselben Port zu binden, ist das Verhalten für alle Sockets, die an diesen Port gebunden sind, unbestimmt.
Die Ausnahme von diesem nicht deterministischen Verhalten ist ein Multicast-Socket. Wenn zwei Sockets an die gleiche Schnittstelle und denselben Port gebunden sind und Mitglieder derselben Multicastgruppe sind, werden Die Daten an beide Sockets übermittelt, und nicht an eine willkürlich ausgewählte.
Verwenden von SO_EXCLUSIVEADDRUSE
Bevor die SO_EXCLUSIVEADDRUSE Socketoption eingeführt wurde, konnte ein Netzwerkanwendungsentwickler nur sehr wenig tun, um zu verhindern, dass ein schädliches Programm an den Port gebunden ist, an den die Netzwerkanwendung eigene Sockets gebunden hatte. Um dieses Sicherheitsproblem zu beheben, hat Windows Sockets die SO_EXCLUSIVEADDRUSE Socketoption eingeführt, die unter Windows NT 4.0 mit Service Pack 4 (SP4) und höher verfügbar wurde.
Die SO_EXCLUSIVEADDRUSE Socketoption kann nur von Mitgliedern der Sicherheitsgruppe "Administratoren" unter Windows XP und früheren Versionen verwendet werden. Die Gründe für die Änderung dieser Anforderung unter Windows Server 2003 und höher werden weiter unten im Artikel erläutert.
Indem die Funktion setsockopt aufgerufen wird, wird die Option SO_EXCLUSIVEADDRUSE festgelegt, wobei der Parameter optname auf SO_EXCLUSIVEADDRUSE gesetzt wird und der Parameter optval auf einen booleschen Wert von TRUE gesetzt wird, bevor der Socket gebunden wird. Nachdem die Option festgelegt wurde, unterscheidet sich das Verhalten der nachfolgenden bind Aufrufe je nach der Netzwerkadresse, die in jedem bind Aufruf angegeben ist.
Die folgende Tabelle beschreibt das Verhalten, das in Windows XP und früher auftritt, wenn ein zweiter Socket versucht, eine Bindung an eine Adresse durchzuführen, die zuvor von einem ersten Socket mithilfe bestimmter Socketoptionen gebunden wurde.
Anmerkung
In der folgenden Tabelle bezeichnet "Wildcard" die Wildcardadresse für das angegebene Protokoll (z. B. "0.0.0.0", für IPv4 und "::" für IPv6). "Specific" bezeichnet eine bestimmte IP-Adresse, die einer Schnittstelle zugewiesen ist. Die Tabellenzellen geben an, ob die Verbindung erfolgreich ist ("Erfolg") oder ob ein Fehler angezeigt wird ("INUSE" für den WSAEADDRINUSE Fehler; "ACCESS" für den WSAEACCES Fehler).
Erster Aufruf von bind | Zweiter Aufruf von bind | ||||||
Standard | SO_REUSEADDR | SO_EXCLUSIVEADDRUSE | |||||
Platzhalter | Spezifisch | Platzhalter | Spezifisch | Platzhalter | Spezifisch | ||
Standard | Platzhalter | INUSE | INUSE | Erfolg | Erfolg | INUSE | INUSE |
Spezifisch | INUSE | INUSE | Erfolg | Erfolg | INUSE | INUSE | |
SO_REUSEADDR | Platzhalter | INUSE | INUSE | Erfolg | Erfolg | INUSE | INUSE |
Spezifisch | INUSE | INUSE | Erfolg | Erfolg | INUSE | INUSE | |
SO_EXCLUSIVEADDRUSE | Platzhalter | INUSE | INUSE | ZUGANG | ZUGANG | INUSE | INUSE |
Spezifisch | INUSE | INUSE | ZUGANG | ZUGANG | INUSE | INUSE |
Wenn zwei Sockets an dieselbe Portnummer gebunden sind, aber auf unterschiedlichen expliziten Schnittstellen, besteht kein Konflikt. Wenn beispielsweise ein Computer über zwei IP-Schnittstellen verfügt, 10.0.0.1 und 10.99.99.99. Wenn der erste Aufruf an bind auf 10.0.0.1 festgelegt ist, wobei der Port auf 5150 und SO_EXCLUSIVEADDRUSE festgelegt ist, dann wird ein zweiter Aufruf, die Funktion bind auf 10.99.99.99 abzurufen, wobei der Port ebenfalls auf 5150 festgelegt ist und keine Optionen angegeben werden, erfolgreich sein. Wenn jedoch der erste Socket an die Platzhalteradresse und Port 5150 gebunden ist und SO_EXCLUSIVEADDRUSE festgelegt ist, schlägt jeder nachfolgende Bindungsaufruf an Port 5150 fehl, wobei entweder WSAEADDRINUSE oder WSAEACCES vom Bindungsvorgang zurückgegeben wird.
Wenn der erste Aufruf von bind entweder SO_REUSEADDR setzt oder gar keine Socketoptionen festlegt, wird der zweite Aufruf von bind den Port "übernehmen" und die Anwendung kann nicht bestimmen, welcher der beiden Sockets bestimmte Pakete erhalten hat, die an den "gemeinsamen" Port gesendet werden.
Eine typische Anwendung, die die Bind--Funktion aufruft, weist den gebundenen Socket nicht für die ausschließliche Verwendung zu, es sei denn, die SO_EXCLUSIVEADDRUSE-Socketoption wird für den Socket aufgerufen, bevor die Bind--Funktion aufgerufen wird. Wenn eine Clientanwendung an einen kurzlebigen Port oder einen bestimmten Port bindet, bevor eine Serveranwendung an denselben Port gebunden wird, können Probleme auftreten. Die Serveranwendung kann mithilfe der SO_REUSEADDR-Socketoption den Socket vor dem Aufrufen der bind-Funktion zwangsweise an denselben Port binden, aber das Verhalten aller an diesen Port gebundenen Sockets ist dann unvorhersehbar. Wenn die Serveranwendung versucht, die SO_EXCLUSIVEADDRUSE Socketoption für die ausschließliche Verwendung des Ports zu verwenden, schlägt die Anforderung fehl.
Umgekehrt kann ein Socket, für den SO_EXCLUSIVEADDRUSE festgelegt ist, nicht unbedingt sofort nach dem Schließen des Sockets wiederverwendet werden. Wenn beispielsweise ein Überwachungssocket mit SO_EXCLUSIVEADDRUSE Set eine Verbindung akzeptiert und anschließend geschlossen wird, kann ein anderer Socket (auch mit SO_EXCLUSIVEADDRUSE) nicht an denselben Port wie der erste Socket gebunden werden, bis die ursprüngliche Verbindung inaktiv wird.
Dieses Problem kann kompliziert werden, da das zugrunde liegende Transportprotokoll die Verbindung möglicherweise nicht beendet, obwohl der Socket geschlossen wurde. Selbst nachdem der Socket von der Anwendung geschlossen wurde, muss das System alle gepufferten Daten übertragen, eine ordnungsgemäße Trennungsnachricht an den Peer senden und auf eine entsprechende ordnungsgemäße Trennungsnachricht vom Peer warten. Es ist möglich, dass das zugrunde liegende Transportprotokoll die Verbindung niemals freigeben kann; Beispielsweise kann der Peer, der an der ursprünglichen Verbindung teilnimmt, ein Fenster mit null Größe oder eine andere Form von "Angriffskonfiguration" ankündigen. In einem solchen Fall verbleibt die Clientverbindung trotz der Anforderung zum Schließen in einem aktiven Zustand, da nicht bekannte Daten im Puffer verbleiben.
Um diese Situation zu vermeiden, sollten Netzwerkanwendungen ein ordnungsgemäßes Herunterfahren sicherstellen, indem sie shutdown mit gesetztem SD_SEND-Flag aufrufen und dann in einer recv-Schleife warten, bis über die Verbindung null Bytes zurückgegeben werden. Dies stellt sicher, dass alle Daten vom Peer empfangen werden und bestätigt dem Peer ebenso, dass alle übertragenen Daten empfangen wurden, und vermeidet gleichzeitig das zuvor erwähnte Problem der Portwiederverwendung.
Die SO_LINGER Socketoption kann auf einem Socket festgelegt werden, um zu verhindern, dass der Port in einen "aktiven" Wartezustand wechselt; Dies wird jedoch abgeraten, da dies zu unerwünschten Effekten führen kann, z. B. zum Zurücksetzen von Verbindungen. Wenn beispielsweise Daten vom Peer empfangen werden, aber nicht von diesem bestätigt werden, und der lokale Computer den Socket mit der Option SO_LINGER schließt, wird die Verbindung zwischen den beiden Computern zurückgesetzt und die nicht bestätigten Daten werden vom Peer verworfen. Die Auswahl einer geeigneten Zeit für das Warten ist schwierig, da ein kleinerer Timeoutwert häufig zu plötzlich abgebrochenen Verbindungen führt, während größere Timeoutwerte das System anfällig für Denial-of-Service-Angriffe lassen (indem viele Verbindungen eingerichtet werden, die möglicherweise Anwendungsthreads blockieren oder verzögern). Das Schließen eines Sockets mit einem Timeoutwert ungleich Null für die Verweilzeit kann auch dazu führen, dass der closesocket-Aufruf blockiert wird.
Erweiterte Socketsicherheit
Die erweiterte Socketsicherheit wurde mit der Version von Windows Server 2003 hinzugefügt. In früheren Versionen des Microsoft Server-Betriebssystems erlaubte die Standardsocketsicherheit problemlos Prozesse, um Ports von nicht ahnungslosen Anwendungen zu entjacken. In Windows Server 2003 befinden sich Sockets standardmäßig nicht in einem teilbaren Zustand. Wenn eine Anwendung daher anderen Prozessen erlauben möchte, einen Port wiederzuverwenden, an den ein Socket bereits gebunden ist, muss er ihn speziell aktivieren. In diesem Fall muss für den ersten Socket, der bind für den Port aufruft, SO_REUSEADDR für den Socket festgelegt sein. Die einzige Ausnahme in diesem Fall tritt auf, wenn der zweite Binden Aufruf durch dasselbe Benutzerkonto ausgeführt wird, das den ursprünglichen Aufruf zu Bindendurchgeführt hat. Diese Ausnahme besteht ausschließlich für die Abwärtskompatibilität.
In der folgenden Tabelle wird das Verhalten beschrieben, das in Windows Server 2003 und höher auftritt, wenn ein zweiter Socket versucht, eine Bindung an eine Adresse durchzuführen, die zuvor von einem ersten Socket mit bestimmten Socketoptionen gebunden wurde.
Anmerkung
In der folgenden Tabelle bezeichnet "Wildcard" die Wildcardadresse für das angegebene Protokoll (z. B. "0.0.0.0", für IPv4 und "::" für IPv6). "Specific" bezeichnet eine bestimmte IP-Adresse, die einer Schnittstelle zugewiesen ist. Die Tabellenzellen zeigen an, ob die Verbindung erfolgreich war („Erfolg“) oder welcher Fehler zurückgegeben wurde („INUSE“ für den WSAEADDRINUSE Fehler; „ACCESS“ für den WSAEACCES Fehler).
Beachten Sie außerdem, dass in dieser speziellen Tabelle beide bind-Aufrufe unter demselben Benutzerkonto erfolgen.
Erster Aufruf von bind | Zweiter Aufruf von bind | ||||||
Standard | SO_REUSEADDR | SO_EXCLUSIVEADDRUSE | |||||
Platzhalter | Spezifisch | Platzhalter | Spezifisch | Platzhalter | Spezifisch | ||
Standard | Platzhalter | INUSE | Erfolg | ZUGANG | Erfolg | INUSE | Erfolg |
Spezifisch | Erfolg | INUSE | Erfolg | ZUGANG | INUSE | INUSE | |
SO_REUSEADDR | Platzhalter | INUSE | Erfolg | Erfolg | Erfolg | INUSE | Erfolg |
Spezifisch | Erfolg | INUSE | Erfolg | Erfolg | INUSE | INUSE | |
SO_EXCLUSIVEADDRUSE | Platzhalter | INUSE | ZUGANG | ZUGANG | ZUGANG | INUSE | ZUGANG |
Spezifisch | Erfolg | INUSE | Erfolg | ZUGANG | INUSE | INUSE |
Einige Einträge in der obigen Tabelle verdienen eine Erläuterung.
Wenn beispielsweise der erste Aufrufer SO_EXCLUSIVEADDRUSE für eine bestimmte Adresse festlegt und der zweite Aufrufer versucht, bind mit einer Platzhalteradresse auf demselben Port aufzurufen, ist der zweite bind-Aufruf erfolgreich. In diesem speziellen Fall ist der zweite Aufrufer an alle Schnittstellen gebunden, mit Ausnahme der spezifischen Adresse, an die der erste Aufrufer gebunden ist. Beachten Sie, dass die Umkehrung dieses Falls nicht zutrifft: Wenn der erste Aufrufer SO_EXCLUSIVEADDRUSE festlegt und bind mit dem Platzhalter-Flag aufruft, kann der zweite Aufrufer bind mit demselben Port nicht aufrufen.
Das Verhalten der Socketbindung ändert sich, wenn die Socketbindungsaufrufe unter verschiedenen Benutzerkonten erfolgen. Die folgende Tabelle gibt das Verhalten an, das in Windows Server 2003 und höher auftritt, wenn ein zweiter Socket versucht, eine Bindung an eine Adresse durchzuführen, die zuvor von einem ersten Socket gebunden wurde, mithilfe bestimmter Socketoptionen und eines anderen Benutzerkontos.
Erster Aufruf von bind | Zweiter Aufruf von bind | ||||||
Standard | SO_REUSEADDR | SO_EXCLUSIVEADDRUSE | |||||
Platzhalter | Spezifisch | Platzhalter | Spezifisch | Platzhalter | Spezifisch | ||
Standard | Platzhalter | INUSE | ZUGANG | ZUGANG | ZUGANG | INUSE | ZUGANG |
Spezifisch | Erfolg | INUSE | Erfolg | ZUGANG | INUSE | INUSE | |
SO_REUSEADDR | Platzhalter | INUSE | ZUGANG | Erfolg | Erfolg | INUSE | ZUGANG |
Spezifisch | Erfolg | INUSE | Erfolg | Erfolg | INUSE | INUSE | |
SO_EXCLUSIVEADDRUSE | Platzhalter | INUSE | ZUGANG | ZUGANG | ZUGANG | INUSE | ZUGANG |
Spezifisch | Erfolg | INUSE | Erfolg | ZUGANG | INUSE | INUSE |
Beachten Sie, dass sich das Standardverhalten unterscheidet, wenn die bind-Aufrufe unter verschiedenen Benutzerkonten erfolgen. Wenn der erste Aufrufer keine Optionen für den Socket festlegt und an die Platzhalteradresse bindet, kann der zweite Aufrufer die Option SO_REUSEADDR nicht festlegen und an denselben Port erfolgreich binden. Das Standardverhalten ohne festgelegte Optionen gibt auch einen Fehler zurück.
Unter Windows Vista und höher kann ein dualer Stapelsocket erstellt werden, der sowohl IPv6 als auch IPv4 verwendet. Wenn ein Dual-Stack-Socket an die Platzhalteradresse gebunden ist, wird der angegebene Port sowohl in den IPv4- als auch in den IPv6-Netzwerkstapeln reserviert und die mit SO_REUSEADDR und SO_EXCLUSIVEADDRUSE (sofern festgelegt) verknüpften Prüfungen durchgeführt. Diese Prüfungen müssen in beiden Netzwerkstapeln erfolgreich ausgeführt werden. Wenn z. B. ein Dualstapel-TCP-Socket SO_EXCLUSIVEADDRUSE festlegt und dann versucht, eine Bindung an Port 5000 herzustellen, kann zuvor kein anderer TCP-Socket an Port 5000 (entweder Wildcard oder spezifisch) gebunden werden. Wenn in diesem Fall zuvor ein IPv4-TCP-Socket an die Loopbackadresse an Port 5000 gebunden war, würde der bind-Aufruf für den Dual-Stack-Socket mit WSAEACCES fehlschlagen.
Anwendungsstrategien
Bei der Entwicklung von Netzwerkanwendungen, die auf socketebene ausgeführt werden, ist es wichtig, die Art der erforderlichen Socketsicherheit zu berücksichtigen. Clientanwendungen – Anwendungen, die Daten an einen Dienst verbinden oder senden – erfordern selten zusätzliche Schritte, da sie an einen zufälligen lokalen (kurzlebigen) Port gebunden sind. Wenn für den Client eine bestimmte lokale Portbindung erforderlich ist, um ordnungsgemäß zu funktionieren, müssen Sie die Socketsicherheit in Betracht ziehen.
Die option SO_REUSEADDR hat nur sehr wenige Verwendungen in normalen Anwendungen, abgesehen von Multicast-Sockets, bei denen Daten an alle Sockets übermittelt werden, die an demselben Port gebunden sind. Andernfalls sollte jede Anwendung, die diese Socketoption festlegt, neu gestaltet werden, um die Abhängigkeit zu entfernen, da sie besonders anfällig für "Socket-Entführer" ist. Solange die Socket-Option SO_REUSEADDR dazu verwendet werden kann, einen Port in einer Server-Anwendung potenziell zu kapern, muss die Anwendung als nicht sicher betrachtet werden.
Alle Serveranwendungen müssen SO_EXCLUSIVEADDRUSE für eine starke Socketsicherheit festlegen. Es verhindert nicht nur, dass bösartige Software den Port entführert, sondern gibt auch an, ob eine andere Anwendung an den angeforderten Port gebunden ist. Beispielsweise schlägt ein Aufruf von bind für die Platzhalteradresse durch einen Prozess mit der festgelegten Socket-Option SO_EXCLUSIVEADDRUSE fehl, wenn ein anderer Prozess derzeit an denselben Port auf einer bestimmten Schnittstelle gebunden ist.
Schließlich sollte eine Anwendung, auch wenn die Socketsicherheit in Windows Server 2003 verbessert wurde, immer die SO_EXCLUSIVEADDRUSE Socketoption festlegen, um sicherzustellen, dass sie an alle spezifischen Schnittstellen gebunden wird, die der Prozess angefordert hat. Die Socketsicherheit in Windows Server 2003 erhöht die Sicherheit für Ältere Anwendungen, anwendungsentwickler müssen ihre Produkte jedoch weiterhin mit allen Aspekten der Sicherheit entwerfen.