Zugangsdaten in URLs im Log unkenntlich machen - #3780
Open
andreasmuellerka wants to merge 1 commit into
Open
Conversation
Ein Passwort, das als URL-userinfo übergeben wird (schema://benutzer:passwort@host/), steht im Klartext im Log. RedactingFilter greift nicht, weil alle drei REDACTION_PATTERNS an einem Feldnamen ansetzen und die userinfo einer URL nach RFC 3986 keinen hat. Mehrere SoC-Module - json, http, homeassistant, psacc - bieten ein freies url-Feld und keine getrennten Felder für Benutzer und Passwort. Für einen Endpunkt hinter Basic Auth ist es der einzige Weg, die Zugangsdaten in die URL zu schreiben. Zwei Stellen protokollieren eine solche URL: - packages/modules/vehicles/json/soc.py gibt die konfigurierte URL auf Debug-Level aus, das landet in soc.log - packages/helpermodules/subdata.py protokolliert jede MQTT-Nachricht samt Payload, damit landet die Modulkonfiguration selbst in mqtt.log An beiden Handlern hängt bereits ein RedactingFilter. Die Absicht, Geheimnisse aus diesen Dateien herauszuhalten, ist also vorhanden - es fehlte lediglich das Muster für diese Form. Das neue Muster wirkt in redact_sensitive_info() und damit für jeden Handler, an dem bereits ein RedactingFilter hängt. Der Benutzername bleibt sichtbar, ersetzt wird nur das Passwort: Bei der Diagnose eines Authentifizierungsproblems ist die Auskunft, mit welchem Benutzer verbunden wurde, der nützliche Teil der Logzeile. Der Wertteil ist bewusst greedy. Enthält das Passwort selbst ein @, reicht der Treffer bis zum letzten @ vor dem Host statt nur bis zum ersten. In allen übrigen Fällen sind beide Varianten identisch. Schrägstrich und Whitespace bleiben ausgeschlossen, dadurch kann ein Treffer nie über die Authority hinaus in Pfad oder Query laufen - eine Mailadresse in einem Query-Parameter bleibt unangetastet, was ein Test abdeckt. Die beiden Excepthooks schreiben über open()/write() in thread_errors.log und umgehen damit das Logging-Framework und den Filter. Eine ungefangene Exception, die eine URL mit sich trägt - etwa ein InvalidURI aus einem Verbindungsaufruf -, landet dort im Klartext. Sie führen ihren Text jetzt durch dieselbe Funktion; aus print_tb() wurde format_tb(), weil sich nur ein String filtern lässt, die Ausgabe bleibt unverändert.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Ein Passwort, das als URL-userinfo übergeben wird (
schema://benutzer:passwort@host/), steht im Klartext im Log.RedactingFiltergreift nicht: Alle dreiREDACTION_PATTERNSsetzen an einem Feldnamen an (password=…,"password": "…"), und die userinfo einer URL nach RFC 3986 hat keinen.Das ist kein Randfall. Mehrere SoC-Module —
json,http,homeassistant,psacc— bieten ein freiesurl-Feld und keine getrennten Felder für Benutzer und Passwort. Für einen Endpunkt hinter Basic Auth ist es der einzige Weg, die Zugangsdaten in die URL zu schreiben, undrequestsunterstützt genau das.Zwei Stellen protokollieren eine solche URL:
packages/modules/vehicles/json/soc.pygibt die konfigurierte URL auf Debug-Level aus →soc.logpackages/helpermodules/subdata.pyprotokolliert jede MQTT-Nachricht samt Payload, damit landet die Modulkonfiguration selbst inmqtt.logAn beiden Handlern hängt bereits ein
RedactingFilter. Die Absicht, Geheimnisse aus diesen Dateien herauszuhalten, ist also vorhanden — es fehlte lediglich das Muster für diese Form.Reproduktion
Ein JSON-SoC-Modul mit
https://benutzer:geheim@nas.local/soc.jsonkonfiguriert und Debug-Logging aktiviert, ergibt auf dem aktuellen master:Mit dieser Änderung steht in beiden Dateien
https://benutzer:***REDACTED***@nas.local/soc.json.Änderung
Ein Muster mehr in
redact_sensitive_info(), damit wirkt es für jeden Handler, an dem bereits einRedactingFilterhängt:Der Benutzername bleibt sichtbar, ersetzt wird nur das Passwort. Bei der Diagnose eines Authentifizierungsproblems ist die Auskunft, mit welchem Benutzer verbunden wurde, der nützliche Teil der Logzeile.
Der Wertteil ist bewusst greedy: Enthält das Passwort selbst ein
@, reicht der Treffer bis zum letzten@vor dem Host statt nur bis zum ersten. In allen übrigen Fällen sind beide Varianten identisch. Schrägstrich und Whitespace bleiben ausgeschlossen, dadurch kann ein Treffer nie über die Authority hinaus in Pfad oder Query laufen — eine Mailadresse in einem Query-Parameter bleibt unangetastet.thread_errors.log
Die beiden Excepthooks in
setup_logging()schreiben überopen()/write()und umgehen damit das Logging-Framework und den Filter. Eine ungefangene Exception, die eine URL mit sich trägt — etwa einInvalidURIaus einem Verbindungsaufruf —, landet dort im Klartext. Sie führen ihren Text jetzt durch dieselbe Funktion. Ausprint_tb()wurdeformat_tb(), weil sich nur ein String filtern lässt; die Ausgabe bleibt unverändert.Tests
Neu ist
packages/helpermodules/logger_test.pymit zehn Fällen, darunter drei, die unverändert bleiben müssen: eine URL ohne Zugangsdaten, ein@in einem Query-Parameter und eine Mailadresse hinter einer URL.Ein dokumentierter Randfall: Heißt der Benutzer wie ein Eintrag aus
KNOWN_SENSITIVE_FIELDS(token,secret, …), greift zusätzlich das bestehende Feldmuster und kürzt die URL aufws://token=***REDACTED***, weil dessen Wertmuster[^\s&]+auch/und@erlaubt. Das Passwort ist auch in diesem Fall entfernt, es fehlen lediglich Host und Pfad in der Logzeile. Das Verhalten ist von der Reihenfolge der beiden Ersetzungen unabhängig und durch einen Test festgehalten.