Named Pipes unter Windows öffnen Sicherheitslücken für lokale Angriffe

Named Pipes in Windows sind eine beliebte IPC-Methode, bergen jedoch erhebliche Sicherheitsrisiken für lokale Angriffe.

Der Artikel erklärt, warum lokale Named Pipes nicht vertrauenswürdig sind und wie man sie absichert.
Highlights
  • Ein privilegierter Windows-Dienst als Named-Pipe-Server kann zum Ziel von Angriffen werden, wenn die Pipe nicht richtig geschützt ist.
  • Jede über die Pipe empfangene Nachricht muss als nicht vertrauenswürdige Eingabe behandelt werden, um den Confused Deputy zu vermeiden.
  • Eine sichere Named-Pipe-Implementierung erfordert eine Kombination aus Zugriffskontrolle, Autorisierung und Eingabevalidierung.

Named Pipes sind unter Windows-Entwicklern ein beliebtes Mittel für die Interprozesskommunikation (IPC) zwischen Anwendungen auf demselben Rechner. Sie sind schnell, tief im Betriebssystem verankert und eignen sich hervorragend für den Datenaustausch zwischen Windows-Diensten, Desktop-Anwendungen, Tray-Prozessen und Hintergrund-Agents. Die landläufige Annahme, dass diese Kommunikation aufgrund der Lokalität vertrauenswürdig sei, ist jedoch ein gefährlicher Trugschluss. In der Realität ist die Pipe, auf die viele unterschiedliche Prozesse mit verschiedenen Benutzerkonten und Sicherheitskontexten zugreifen können, eine exponierte lokale Schnittstelle, die ein erhebliches Sicherheitsrisiko darstellt.

Lokal bedeutet nicht vertrauenswürdig

Ein typisches Szenario: Ein privilegierter Windows-Dienst (z. B. als LocalSystem) fungiert als Named-Pipe-Server, während eine Desktop-Anwendung mit geringeren Rechten als Client agiert. Da beide Prozesse auf demselben Rechner laufen, wird die Kommunikation als intern und sicher behandelt. Jeder Prozess auf dem Rechner, der den Namen der Pipe kennt und über die entsprechenden Zugriffsrechte verfügt, kann jedoch versuchen, eine Verbindung herzustellen. Windows prüft nicht, welche Anwendung die Verbindung aufbauen will. Daher muss eine Named Pipe als exponierte Schnittstelle betrachtet werden, die durch Autorisierung und Validierung geschützt werden muss.

Identität, Zugriffskontrolle und Berechtigungsgrenzen

Das größte Risiko besteht, wenn ein privilegierter Windows-Dienst (LocalSystem) mit einer weniger privilegierten Desktop-Anwendung kommuniziert. Ein LocalSystem-Dienst kann sensible Operationen wie das Ändern von Systemdateien, das Starten von Prozessen oder den Zugriff auf Daten anderer Benutzer ausführen. Wird dies über eine Named Pipe zugänglich gemacht, wird die Pipe zu einer API für privilegierte Funktionen. Eine erfolgreiche Verbindung beweist nur, dass der Client die Pipe öffnen durfte, nicht jedoch, dass es sich um die richtige Anwendung oder einen autorisierten Benutzer handelt. Pipe-Berechtigungen sollten daher explizit definiert und auf das Nötigste beschränkt werden. Authentifizierung und Autorisierung müssen getrennt betrachtet werden: Selbst wenn ein Benutzer den Status abfragen darf, sollte er nicht automatisch die Möglichkeit haben, den Dienst zu stoppen. Jeder sensitive Befehl muss individuell autorisiert werden. Impersonation (Identitätswechsel) kann dabei helfen, denn sie führt Operationen im Sicherheitskontext des Clients aus. Dies muss jedoch mit Vorsicht geschehen: Der Server muss prüfen, ob die Impersonation erfolgreich war, und nach der Ausführung stets zur eigenen Identität zurückkehren.

Unsere Server, Befehle und Daten

Der Client muss den Server ebenso überprüfen wie der Server den Client. Ein vorhersagbarer Pipe-Name ist kein Geheimnis. Ein Angreifer kann eine Pipe mit dem erwarteten Namen erstellen, bevor der legitime Server startet, und so den Client kapern. Die Option „First-Pipe-Instance“ hilft, die Neuanlage einer bereits existierenden Pipe zu verhindern, ersetzt aber keine echten Zugriffskontrollen. Jede über die Pipe empfangene Nachricht muss als nicht vertrauenswürdige Eingabe behandelt werden. Ein authentifizierter Client kann fehlerhafte Payloads, ungültige Pfade oder bösartige Befehle senden. Ein privilegierter Dienst, der diese Eingaben direkt in Datei- oder Registry-Operationen umwandelt, wird zum „Confused Deputy“ (verwirrter Helfer): Der Angreifer liefert die Anweisung, der Dienst die Privilegien.

Verfügbarkeit und Remote-Zugriff

Die Risiken beschränken sich nicht auf Privilegieneskalation und unbefugte Befehle. Ein bösartiger oder fehlerhafter Prozess kann sich ständig verbinden, Verbindungen offenhalten oder teure Operationen auslösen, was zu einem Denial-of-Service führt. Der Server sollte daher Begrenzungen für gleichzeitige Verbindungen, Timeouts und Nachrichtengrößen einführen. Zudem wird oft fälschlicherweise angenommen, dass Named Pipes nur lokal erreichbar sind. Windows unterstützt jedoch auch Remote-Zugriff auf Named Pipes. Für rein lokale Kommunikation sollte die Pipe explizit so konfiguriert werden, dass sie Remote-Clients oder Netzwerkidentitäten (wie NT AUTHORITY\NETWORKcode) abweist.

Wenn eine Named Pipe zur Sicherheitsgrenze wird

Eine Named Pipe wird dann zu einer Sicherheitsgrenze, wenn die Prozesse an ihren Enden unterschiedliche Privilegien oder Vertrauensstufen haben. Ein typisches Beispiel ist ein LocalSystem-Dienst, der mit einer Standard-Benutzeranwendung kommuniziert. Der Dienst kann geschützte Dateien ändern, Prozesse starten und auf die Daten anderer Benutzer zugreifen. Die Desktop-Anwendung kann dies normalerweise nicht. Wenn der Dienst Befehle über eine Named Pipe akzeptiert, wird diese Pipe zur Schnittstelle für diese privilegierten Fähigkeiten. Jede Schwachstelle in den Berechtigungen, Identitätsprüfungen oder der Befehlsvalidierung ermöglicht es einem nicht vertrauenswürdigen lokalen Prozess, die Privilegien des Dienstes zu missbrauchen. Der Server muss die Sicherheitsidentität hinter der Verbindung validieren und nicht nur den Prozessnamen oder den geheimen Pipe-Namen überprüfen.

Eine Anfrage wie Datei lesen: C:\ProgramData\Product\status.jsoncode wird gefährlich, wenn der Client den Pfad auf C:\Windows\System32\config\SAMcode ändern kann. Ein sicherer Server muss daher eine Reihe von Prüfungen durchführen: Verifikation der Windows-Identität des Clients, eine restriktive Zugriffsliste (DACL) für die Pipe, unabhängige Autorisierung jedes Befehls und Validierung aller Pfade. Der Grundsatz lautet: Der Pipe-Server darf eine Operation niemals nur ausführen, weil ein Client sie angefordert hat. Er darf sie erst ausführen, nachdem er bestätigt hat, wer sie anfordert, ob diese Identität autorisiert ist und ob die Anfrage innerhalb der Sicherheitsgrenzen bleibt.

Praktische Maßnahmen zur Zugriffskontrolle

Der Server sollte bereits vor der Verarbeitung von Nachrichten bestimmen, wer eine Verbindung aufbauen darf. Die DACL der Pipe kontrolliert den Zugriff auf beide Enden. Eine Standard-DACL ist riskant, da ihre Berechtigungen oft zu weit gefasst sind. Für die lokale Kommunikation zwischen Anwendungen können beide Seiten den Prozess am anderen Ende der Pipe überprüfen: Der Server kann GetNamedPipeClientProcessIdcode aufrufen, der Client GetNamedPipeServerProcessIdcode. Eine starke Implementierung kombiniert mehrere Kontrollen: eine explizite DACL, die Verifikation der Windows-Identität (SID), die Autorisierung für jeden Befehl und die Validierung der Nachrichteninhalte. Die Verbindung sollte abgelehnt werden, wenn die Identitätsprüfung fehlschlägt.

Impersonation sorgfältig einsetzen

Named-Pipe-Impersonation erlaubt es dem Server, vorübergehend im Sicherheitskontext des Clients zu arbeiten. Windows prüft dann den Ressourcenzugriff mit dem Token des Clients, nicht mit dem des Dienstkontos. In .NET bietet NamedPipeServerStream.RunAsClientcode eine kontrollierte Methode. Dies ist nützlich, wenn der Client eine Operation nur dann ausführen können soll, wenn sein Konto bereits die Berechtigung dafür hat. Impersonation ersetzt jedoch nicht die Autorisierung. Ein Dienst sollte beispielsweise nicht ohne weiteres zwischen der Client- und der Dienst-Identität wechseln. Der sicherere Ansatz besteht darin, die Operation in klar definierte Phasen zu unterteilen: Authentifizierung und Autorisierung des Clients, Validierung aller Daten, Impersonation nur für die tatsächliche Client-Operation und dann die Rückkehr zur eigenen Identität für die restliche Arbeit. Fehler bei der Impersonation müssen dazu führen, dass die Anfrage abgelehnt wird, da der Vorgang sonst fälschlicherweise mit den Service-Privilegien ausgeführt würde.

Pipe-Nachrichten als nicht vertrauenswürdige Eingabe

Selbst die Verifikation des verbundenen Prozesses macht die Nachrichten nicht sicher. Die legitime Anwendung könnte kompromittiert sein oder benutzergesteuerte Daten an die Pipe senden. Jede Nachricht muss struktur- und inhaltsseitig validiert werden. Ein gefährliches Szenario ist das direkte Deserialisieren einer Anfrage: Ein Angreifer könnte so den Dienst anweisen, Dateien außerhalb des Anwendungsverzeichnisses zu überschreiben. Der sicherere Ansatz ist, nur eng definierte Befehle und keine allgemeinen Funktionen wie WriteFile(path, content)code zu exponieren. Das Protokoll sollte eine explizite Rahmung (z. B. einen Header mit Nachrichtenlänge) und strenge Größenbeschränkungen aufweisen. Alle Werte wie Pfade müssen gegen eine Whitelist geprüft und normalisiert werden, um Path-Traversal-Angriffe zu verhindern.

Denial-of-Service und Fernzugriff vermeiden

Ein Named-Pipe-Endpunkt kann vor unbefugten Befehlen geschützt sein und dennoch anfällig für DoS-Angriffe sein. Ein Angreifer kann Verbindungen blockieren, indem er alle verfügbaren Instanzen belegt oder extrem langsam Daten sendet. Ein defensiver Server muss daher Begrenzungen für gleichzeitige Verbindungen, Nachrichtengrößen und die maximale Dauer einer Anfrage einführen. Blockierende Operationen sollten abbrechbar sein. Zudem muss die Möglichkeit des Remote-Zugriffs ausgeschlossen werden. Die native Windows-Funktion PIPE_REJECT_REMOTE_CLIENTScode lehnt Remote-Verbindungen automatisch ab. Alternativ kann die DACL der Pipe den Zugriff für die NT AUTHORITY\NETWORKcode-Identität verweigern. Eine Kombination beider Maßnahmen ist empfehlenswert.

Eine sichere Named-Pipe-Architektur entwerfen

Ein sicheres Design minimiert die Anzahl exponierter Operationen und die Menge an privilegiertem Code, der direkt mit Client-Daten arbeitet. Die Pipe sollte eine schmale Kommunikationsgrenze sein, keine generische Schnittstelle zum Betriebssystem. Das Protokoll sollte Geschäftsvorgänge (z. B. „Policy aktualisieren“) statt Betriebssystem-Primitive (z. B. „Datei schreiben“) exponieren. Zugriff auf die Pipe und die Erlaubnis zur Ausführung eines Befehls müssen getrennt sein. Für besonders sensible Operationen können separate Named Pipes mit jeweils eigenen Zugriffsregeln verwendet werden. Die Komponente, die die Pipe-Nachrichten liest, sollte so wenig privilegierte Arbeit wie möglich verrichten. Sie sollte nur validierte, stark typisierte Anweisungen an eine separate, privilegierte Ausführungsschicht weitergeben. Jede Verbindung sollte einen klaren, begrenzten Lebenszyklus haben: Verbindung annehmen, identifizieren, validieren, autorisieren, ausführen und trennen. Der Server sollte autoritativ sein und die Art und Weise der Ausführung einer Aktion selbst bestimmen, anstatt sie dem Client zu überlassen. Audit-Logs sollten alle sicherheitsrelevanten Ereignisse aufzeichnen.

Checkliste für sichere Named Pipes

Vor der Implementierung sollten Sie die folgenden Punkte prüfen: Definieren Sie die Vertrauensgrenze und behandeln Sie die Pipe als exponierte Schnittstelle. Verwenden Sie eine restriktive DACL. Schließen Sie Remote-Clients aus. Überprüfen Sie beide Endpunkte (Windows-Identität, ggf. Prozess-ID und Signatur). Vertrauen Sie dem Pipe-Namen nicht. Autorisieren Sie jeden Befehl einzeln. Halten Sie das Protokoll eng und exposieren Sie anwendungsspezifische Aktionen. Behandeln Sie alle Nachrichten als nicht vertrauenswürdig. Wenden Sie Größen- und Zeitlimits frühzeitig an. Nutzen Sie Impersonation nur gezielt und in kleinem Umfang. Isolieren Sie die privilegierte Ausführung. Kontrollieren Sie die Ressourcennutzung. Geben Sie kontrollierte Fehlermeldungen zurück. Führen Sie Sicherheitsaudits durch. Scheitern Sie immer sicher (Fail Closed), wenn eine Prüfung nicht bestanden wird.

Eine sichere Named-Pipe-Implementierung stützt sich nicht auf eine einzelne Schutzmaßnahme, sondern auf eine Kombination aus restriktiver Zugriffskontrolle, Endpunktverifikation, operationsspezifischer Autorisierung, strenger Eingabevalidierung, begrenztem Ressourcenverbrauch und eng gefasster privilegierter Funktionalität. Dieser mehrschichtige Ansatz ist der einzige Weg, um Named Pipes sicher im Rahmen einer ansonsten anfälligen lokalen Infrastruktur einzusetzen.

Diesen Artikel teilen