Man kann auf die Speicherung des Kennworts verzichten. Ein mehr als triftiger Grund, wie ich finde.
Ich sehe nicht, wo es einen (entscheidenden) Unterschied macht, ob ich auf dem Client den Hash über Benutzernamen, Realm und Kennwort speichere oder Benutzername und Kennwort selbst. Beide Methoden brauchen den Benutzernamen (im Klartext, weil der außerhalb des Hash-Wertes zusätzlich übermittelt wird als "Key", um welchen Account es sich handelt und wo nach dem Kennwort oder dem Hash zu suchen wäre) und ob ich jetzt das Kennwort oder den "fertigen" Hash A1 (nach RFC2617, Punkt 3.2.2.2) speichere, spielt für die Sicherheit keine wirkliche Rolle - gut schützen muß ich auch auf der Client-Seite beides, wenn ich mit dem Hash dasselbe erreichen kann, wie mit dem Kennwort (siehe auch wieder RFC2617, den kompletten Punkt 4, speziell 4.13). Wenn über Meltdown und/oder Spectre mein Speicher ausgelesen werden kann und da steht der Hash drin, ist das genauso kompromittierend als wenn da ein Kennwort stünde (gut, ein MD5-Hash ist vielleicht etwas schlechter als "secret" zu erkennen als eine Zeichenkette, aber das ist auch nur "gefühlte Sicherheit" durch zusätzliche Verschleierung und hält RE - sofern man die Anwendung auf einem anderen Rechner auch ausführen und dann deren Speicher "ganz legal" durchsuchen kann - keine Stunde stand).
Die Frage, ob ein kompromittiertes Kennwort oder ein kompromittierter Hash-Wert nun "schlimmer" ist, braucht man gar nicht erst zu diskutieren ... "password re-use" ist das Problem des Benutzers und wenn ihm das nicht paßt, kann er selbst einen Hash über sein "Standard-Passwort mit Zusätzen" erzeugen.
Gut, der Server könnte (wenn er ausschließlich "digest auth" unterstützen will, was eben bei TLS zusätzlichen Verkehr ohne zusätzliche Sicherheit bringt) auf die Speicherung des Kennworts für den Benutzer verzichten (macht AVM aber ohnehin nicht, würde auch wieder mit dem Verfahren beim GUI-Login kollidieren) ... solange er niemals auf die Idee kommt/käme, sein "realm" zu verändern - in diesem Moment paßt sein gespeicherter Hash-Wert als A1 auch nicht mehr und (wenn wir mal beim RFC2617 bleiben) auf verschiedene "Schutzzonen" muß er bei diesem Ansatz ebenfalls komplett verzichten.
Hier hinkt Dein Vergleich mit den Linux-Kennworten dann auch wieder ein wenig ... bei so einer "digest auth" kann ich den A1-Hash nur mit festem "realm" speichern (oder der ändert sich auch noch pro Benutzer) und die Kennwörter in der "/etc/shadow" (ich gehe mal davon aus, daß praktisch niemand mehr Kennwörter in einer "/etc/passwd" speichert) sind eben auch "gesalzen", damit ein Brute-Force-Angriff auf die gespeicherten Werte für einen Angreifer entsprechend aufwändig ist. Speichert irgendein Server hingegen den Hash über "username:realm:password" mit einheitlichem "realm" und unter dem "username" als Ordnungskriterium, ist es wieder nur eine Frage der Rechenpower, der Zeit und der Qualität des verwendeten Kennworts. [EDIT: Gut, das ist als Argument meinerseits etwas schwach - auch der "username" als Hash-Bestandteil läßt fertig berechnete Hash-Tables hier ins Leere laufen, da ja auch noch "realm" mit eingeht. Aber das "Prinzip", daß beim Speichern von Kennwörtern in der "/etc/shadow" noch ein "salt" hinzugefügt wird, bleibt trotzdem als Unterschied bestehen, dafür wird da der Benutzername nicht mitgenutzt.]
Ändert der Server den "realm" (wo stünde, daß er das nicht darf - notfalls kann er für jede einzelne Seite einen anderen Wert verwenden, wenn ihm danach ist - siehe RFC2617, Seite 4, erster Absatz), nutzt mir der fertige Hash-Wert A1 auf dem Client auch gar nichts mehr und ich muß ihn neu berechnen. Von Lösungen, die tatsächlich den ersten Teil des Verfahrens (also den MD5-Hash über Benutzernamen, den vom Server übermittelten "realm"-Wert und das Kennwort) gesondert speichern und dann nur noch mit dem Nonce-Wert für eine aktuelle Authentifizierung verknüpfen, halte ich also nicht viel - Dir geht es ja "vom Gefühl" her mit der Abschaffung der CLA (oder dem Verzicht auf sie) auch nicht anders.
Bei der Verwendung von TLS treffen die ganzen Betrachtungen aus dem RFC, die sich mit "eavesdropping" befassen, gar nicht mehr zu ... ein mehr als deutlicher Grund, auf TLS nicht zu verzichten - und damit kommen wir dann zu der Frage, wie man auf der Client-Seite das Speichern von Benutzername/Kennwort vermeiden kann (wenn man statt des Kennworts bisher lieber den Hash gespeichert hatte), wenn man den AVM-Interfaces folgt.
Warum nimmst Du denn dann nicht einfach die Möglichkeit wahr, den verwendeten Account und das Kennwort dadurch besser abzusichern, daß Du über die passende Schnittstelle (das ist iirc "X_AVM-DE_AppSetup:1::RegisterApp()") nur für diese Zugriffe ein passendes App-Konto einrichtest, das man auch noch in den Rechten so beschränken kann (leider nicht sehr fein granuliert, aber besser als gar nichts), daß damit kein anderer Unsinn gemacht werden kann.
Dann braucht es auch genau für dieses "RegisterApp()" eine einmalige Anmeldung mit einem berechtigten Konto (das muß nicht mal volle Rechte haben, wenn es nur die eigenen Rechte an die registrierte App "vererben" soll) und danach auch keinen Benutzernamen und kein Kennwort (für das GUI-Konto) mehr. Ja, man kann jetzt sogar für diese App nur "Phone"-Rechte einfordern, damit kann auch ein erfolgreicher Angreifer auf den Benutzernamen und das Kennwort (für die App) nicht mehr auf der Box anrichten, als es dieses App-Konto zuläßt.
Mich würde interessieren, was bei dir kommt, wenn du mal den oben von mir vorgeschlagenen Code verwendest.
Was erwartest Du denn? Selbst wenn ich den Code anpasse und einen tatsächlich existierenden Benutzernamen (anstelle von "admin") verwende, kann doch beim ersten Versuch nur ein "Unauthenticated" dabei herauskommen, das ist doch genau der Punkt, daß es den zusätzlichen Roundtrip braucht:
Code:
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Header>
<h:Challenge xmlns:h="http://soap-authentication.org/digest/2001/10/" s:mustUnderstand="1">
<Status>Unauthenticated</Status>
<Nonce>E954C424E3C6B92C</Nonce>
<Realm>F!Box SOAP-Auth</Realm>
</h:Challenge>
</s:Header>
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring>UPnPError</faultstring>
<detail>
<UPnPError xmlns="urn:dslforum-org:control-1-0">
<errorCode>503</errorCode>
<errorDescription>Auth. failed</errorDescription>
</UPnPError>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
und das gilt bei mir tatsächlich für die beiden weiter vorne erwähnten Versionen (die Antworten sind also identisch, nur der Nonce-Wert ist natürlich ein anderer).
Das ist auch wieder vollkommen unabhängig davon, ob ich als "pre-auth" die Zuweisung an "$WebClient.Credentials" mache oder nicht - offenbar "überstimmt" hier der SOAP-Header (auf der höheren Protokoll-Ebene) die bereits erfolgte Authentifizierung auf der HTTP-Ebene darunter. Wie gesagt ... mit und ohne Credentials ergibt das (erwartbar) ein "503".
Wenn Du tatsächlich möchtest, daß ich einen
sinnvollen Test mache, ob bei mir die CLA auch innerhalb einer TLS-Verbindung funktioniert, dann fehlt da ja ganz offensichtlich noch der Code für das Berechnen des Hash-Wertes aus Benutzernamen, Realm, Kennwort, Nonce - oder sollte ich den jetzt (just for fun, denn ich halte das ja nicht für notwendig bzw. sinnvoll, siehe oben) selbst hinzufügen?
Wobei es tatsächlich sein kann, daß AVM auch die CLA immer noch zuläßt und es sich hier nur um irgendeinen mysteriösen Fehler handelt (bereite mir eine PS-Version mit CLA vor und ich teste das gerne auch mit der 06.98 für Dich) - oder man hat nur vergessen, den (XML-)Parser auch entsprechend zu ändern.
Bei einem Schema-Fehler im SOAP-Header (z.B. durch das Auslassen des "UserID"-Tags im Header, was ja gültiges XML erzeugt, aber gegen das Schema verstößt) nervt die Box jedenfalls auch bei mir mit einem "401" ... warum das bei Dir aber der Fall sein soll, wenn Du den kompletten SOAP-Header (also von "<s:Header>" bis "</s:Header>" - inklusive) wegläßt, erschließt sich mir auch nicht. Das Ergebnis wäre ja genau derselbe XML-Aufbau, wie ich ihn zuvor hatte und der funktioniert bei mir mit allen FRITZ!OS-Versionen einwandfrei.
Wobei auch das schon wieder Mutmaßungen sind, daß AVM hier irgendein XML-Schema tatsächlich prüft oder berücksichtigt ... eigentlich verstößt selbst das AVM-Beispiel mit der CLA in "First Steps" gegen das XML-Schema aus
SOAPAUTH01 (Anhang A), denn nach:
Code:
<element name="InitChallenge" type="soap-auth:InitChallenge_t"/>
<complexType name="InitChallenge_t">
<sequence>
<element name="UserID" type="xsd:string"/>
<element name="Realm" type="xsd:string"/>
<element name="ClientNonce" type="xsd:string" minOccurs="0"/>
</sequence>
<attribute ref="SOAP-ENV:actor" use="optional"/>
<attribute ref="SOAP-ENV:mustUnderstand" use="optional"/>
<attribute name="digest" type="anyURI" use="optional"/>
</complexType>
ist das "element" mit dem Namen "Realm" in einem "InitChallenge"-Element ja gar nicht optional (wie das bei "ClientNonce" dank des "minOccurs=0"-Attributs der Fall wäre).