- Mitglied seit
- 10 Mai 2006
- Beiträge
- 15,328
- Punkte für Reaktionen
- 1,769
- Punkte
- 113
EDIT: Ich habe den Anhang entfernt, da sich das Ganze nun doch etwas anders entwickelt hat, als ich es ursprünglich erwartete. Es gibt jetzt im Freetz-Trunk die Möglichkeit, das Kennwort des AVM-Zertifikats zu benutzen und auch der Patch für ShellInABox wird dort (hoffentlich) demnächst verfügbar sein.
Seitdem AVM die Möglichkeit eingeführt hat, ein eigenes Zertifikat in der Box zu installieren (oder auch das von der Box selbst generierte eine gewisse Stabilität erreicht hat und sich nicht mehr alle Nase lang ändert), bietet es sich ja an, dieses Zertifikat auch für weitere Programme nutzbar zu machen.
Unter gewissen Umständen ist so eine "Nachnutzung" sogar unumgänglich, denn einige Browser(-Versionen) reagieren etwas allergisch, wenn ihnen für denselben Servernamen (z.B. eben fritz.box oder auch irgendein DynDNS-Name) unterschiedliche Zertifikate vorgesetzt werden, erst recht, wenn das in einem IFRAME innerhalb einer SSL-gesicherten Seite erfolgt.
AVM verschlüsselt aber den privaten Schlüssel für das Zertifikat, der in der Datei /var/flash/websrv_ssl_key.pem gespeichert wird, mit einem Kennwort, das anhand einzigartiger Merkmale der FRITZ!Box (na ja, besser wäre sicherlich "eindeutiger Merkmale") von einer Funktion (securestore_get) in einer AVM-Bibliothek (libboxlib.so) generiert wird. Das ist alles nicht neu und fand schon vor 06.20 im Prinzip genauso statt.
Seit 06.20 wird aber nun dieses Zertifikat (das steht wieder in /var/flash/websrv_ssl_cert.pem) auch für den FTP-Server verwendet, der bis zu diesem Zeitpunkt bei jedem Box-Start ein neues Zertifikat generiert hatte, was natürlich die Identifikation der eigenen FRITZ!Box anhand dieses Zertifikates praktisch unmöglich machte.
Mit der Übernahme des Box-Zertifikates auch für den FTP-Server (der basiert auf dem "ftpd" aus den GNU-Inetutils) hatte AVM aber nun ein Problem (das war auch der eigentliche Grund, warum vorher das Zertifikat stets neu generiert wurde, wenn man dem Kommentar in einer Quelltext-Datei glauben will) - irgendwie mußte der FTP-Daemon in die Lage versetzt werden, das Kennwort für die Entschlüsselung des "private key" zu erfahren, ohne daß man in dessen Quelltext den Aufruf von "securestore_get" einbaut, da dann wieder die GPLv2-Lizenz die Veröffentlichung der Quellen von "libboxlib" erforderlich machen würde. Also wurde das Tool "getprivkeypass" erfunden ...
Dieses kleine Tool bemüht sich nun (im Rahmen seiner Möglichkeiten) bei seinem Start sicherzustellen, daß es tatsächlich vom "ftpd" aus aufgerufen wurde. Ist das erkennbar nicht der Fall, wird ein (festes) Phantasie-Kennwort zurückgeliefert, mit dem natürlich das Keyfile nicht gelesen werden kann. Für die Identifikation des Elternprozesses liest "getprivkeypass" dazu den Inhalt von /proc/$(ppid)/cmdline und /proc/$(ppid)/stat aus und versucht in den gelesenen Daten die Zeichenkette ftpd zu finden. Wenn das erfolgreich ist, reicht das schon als "Beweis", daß der Aufruf aus dem "ftpd" heraus erfolgte und "getprivkeypass" ruft nun "securestore_get" für uns auf. Nach ein wenig Voodoo mit ein paar Bitknipsereien (das macht auch "securestore_get" schon intern ähnlich) rückt "getprivkeypass" aber dann einen Wert heraus, den man mit geeigneten Mitteln (wie, kann man in den Quellen des "ftpd" ja nachlesen) wieder in ein ordentliches Kennwort (8 Zeichen feste Länge zur Zeit) verwandeln kann. Mit diesem Kennwort kann man dann auch den privaten Schlüssel für andere Programme benutzen.
Um also "getprivkeypass" zu "mißbrauchen", benötigt man nichts weiter als ein paar Zeilen C-Code und einen Programmnamen, der irgendwo (der Test erfolgt derzeit mit strstr) die Zeichenfolge "ftpd" enthält. Dazu habe ich ein kleines C-Programm geschrieben, das in nicht allzu ferner Zukunft in einem weiteren Beitrag (und dann sicherlich auch als Vorschlag für ein "enhancement" im Freetz-Trac) auftauchen wird. Damit kann man dann auch einen Apache2-Server (Direktive "SSLPassPhraseDialog") mit dem Box-Zertifikat "füttern" oder meinetwegen auch das Box-Zertifikat (nach entsprechender Umwandlung) für einen Dropbear-SSH-Server auf der Box verwenden. Aber dieses Programm ist hier eigentlich gar nicht das Thema, dieser Ausflug sollte nur die Notwendigkeit und die Möglichkeiten eines solchen "Proxy-Programms" verdeutlichen, mit dem man "getprivkeypass" zur Herausgabe "überreden" kann.
Denn bei dem, was ich eigentlich mit dem statisch gelinkten "shellinaboxd"-Binary erreichen will, wäre die Notwendigkeit eines weiteren Programms ja wenig hilfreich. Also habe ich in meinen Patch für "ShellInABox 2.14" auch noch den Code aufgenommen, um direkt das "getprivkeypass"-Binary aufzurufen, wenn es vorhanden und ausführbar ist und wenn die o.a. Voraussetzungen für das "Verwirren" von "getprivkeypass" auch vorliegen (also der Name des ShellInABox-Daemons irgendwo "ftpd" enthält).
Der Patch imAnhang Freetz-Trunk erweitert also den "shellinaboxd" um eine Option mit dem Namen "--cert-from-box", die den zusätzlichen Code überhaupt erst aktiviert. Für das "Ermitteln" des Kennworts gibt es dann drei mögliche Wege:
1. Die Angabe von "--cert-from-box" erfolgt in einer Form, daß nach der Option gleich noch das Kennwort für den privaten Schlüssel angegeben wird (also "--cert-from-box=boxpassword"). Dann wird genau dieses angegebene Kennwort verwendet, wie das vorher ermittelt wurde, interessiert natürlich nicht. Nachteilig ist es aber weiterhin, daß dann das Kennwort während der gesamten Laufzeit des "shellinaboxd" an diversen Stellen auch abgegriffen werden kann (zu dieser Problematik, von Environment bis /proc/self/cmdline und den jeweiligen Vor- und Nachteilen, gibt es andere ausführlichere Quellen).
2. Es wird kein Kennwort mit der Option "--cert-from-box" festgelegt. Dann prüft der zusätzliche Code als erstes, ob irgendwo im Namen des Programms "ftpd" enthalten ist. Wenn "ftpd" gefunden wird, wird direkt "getprivkeypass" aufgerufen (wenn das Tool auch noch gefunden wird und ausführbar ist), dann braucht es keine weiteren Programme und damit existieren keine weiteren Abhängigkeiten (bei meiner statisch gelinkten Variante). Der Aufruf kann natürlich auch über einen Symlink erfolgen, der den benötigten Aufbau hat ... ich verwende zum Beispiel den Namen "ftpd_siab" für einen Symlink auf "shellinaboxd", damit kommen keine Unklarheiten auf, was sich hinter dem Namen eigentlich verbirgt.
3. Übrig bleibt noch die Form, bei der weder das Kennwort beim Aufruf angegeben wurde noch der Dateiname ein "ftpd" irgendwo enthält. Dann versucht der Code über die Environment-Variable "KEYPASSWORDPROXY" einen Programmnamen für den oben beschriebenen "Proxy" zu lesen und diesen aufzurufen (wieder nach einem Test, ob die Datei existiert und ausführbar ist), um an das Kennwort zu gelangen. Das ist dann zumindest wieder eine Variante, bei der das Kennwort nicht permanent irgendwo im Speicher liegt wie bei Variante 1.
Wenn Box-Key und -Zertifikat nicht gelesen werden können, verweigert der zusätzliche Code bei Angabe von "--cert-from-box" die Arbeit, es wird also auch kein neues Zertifikat für SIAB automatisch generiert.
Ob ich das irgendwann als Patch im Freetz-Trac einreiche, weiß ich noch nicht so genau. Es ist für AVM ja ein Leichtes, den bisher arg blauäugigen Test auf "ftpd" zu verschärfen oder sich wieder etwas Neues einfallen zu lassen, um "getprivkeypass" irgendwie zu ersetzen. Das macht meine Lösung stark vom derzeitigen Stand (gilt von 06.20 bis 06.24) abhängig, falls AVM da irgendetwas dagegen haben sollte. Mir fällt zwar auch nicht ein, was das sein sollte (es spricht für mich deutlich mehr dafür, das Box-Zertifikat mehrfach zu verwenden anstatt es mehrfach an verschiedenen Stellen auf der Box zu speichern), aber man kann ja nie wissen ... ich habe auch absichtlich "nur" den Weg über "getprivkeypass" gewählt und den Aufruf von "securestore_get" außen vor gelassen. Aber ein simples Disassemblieren von "getprivkeypass" reicht ja schon aus, um auch dort die notwendigen Voraussetzungen für den Aufruf zu erkunden. Da das auch die "bad guys" machen könn(t)en, sehe ich die Sicherheit nicht beeinträchtigt.
Wenn man auf der Box ein verschlüsseltes Zertifikat speichert (das ist grundsätzlich auch richtig so in meinen Augen, damit da kein Mißverständnis entsteht) und das muß für die Verwendung automatisch entschlüsselt werden, dann braucht es eben auch einen Weg, das zu tun. Da beißt die Maus keinen Faden ab und wenn damit der private Schlüssel etwas weniger "vertrauenswürdig" ist, muß man das eben beim Umgang mit solchen Verbindungen berücksichtigen. Da kann AVM auch wenig bis nichts dagegen tun ... wer es anders und sicherer haben will, braucht eine Art TPM per USB o.ä. angebunden - das ist dann sogar in meinen Augen für ein Consumer-Gerät eher Overkill, solange solche Teile nicht irgendwo in den Prozessoren direkt eingebaut sind und nur noch benutzt werden müssen.
Ach so, falls sich jemand fragen sollte, was man mit dem Patch nun machen soll ... einfach in das Verzeichnis "make/shellinabox/patches" eines Freetz-Trunks legen (die Erweiterung ".txt" dabei weglassen, das Forum erlaubt nur keine Dateien mit ".patch" als Extension) und dann das Image neu bauen lassen.
Seitdem AVM die Möglichkeit eingeführt hat, ein eigenes Zertifikat in der Box zu installieren (oder auch das von der Box selbst generierte eine gewisse Stabilität erreicht hat und sich nicht mehr alle Nase lang ändert), bietet es sich ja an, dieses Zertifikat auch für weitere Programme nutzbar zu machen.
Unter gewissen Umständen ist so eine "Nachnutzung" sogar unumgänglich, denn einige Browser(-Versionen) reagieren etwas allergisch, wenn ihnen für denselben Servernamen (z.B. eben fritz.box oder auch irgendein DynDNS-Name) unterschiedliche Zertifikate vorgesetzt werden, erst recht, wenn das in einem IFRAME innerhalb einer SSL-gesicherten Seite erfolgt.
AVM verschlüsselt aber den privaten Schlüssel für das Zertifikat, der in der Datei /var/flash/websrv_ssl_key.pem gespeichert wird, mit einem Kennwort, das anhand einzigartiger Merkmale der FRITZ!Box (na ja, besser wäre sicherlich "eindeutiger Merkmale") von einer Funktion (securestore_get) in einer AVM-Bibliothek (libboxlib.so) generiert wird. Das ist alles nicht neu und fand schon vor 06.20 im Prinzip genauso statt.
Seit 06.20 wird aber nun dieses Zertifikat (das steht wieder in /var/flash/websrv_ssl_cert.pem) auch für den FTP-Server verwendet, der bis zu diesem Zeitpunkt bei jedem Box-Start ein neues Zertifikat generiert hatte, was natürlich die Identifikation der eigenen FRITZ!Box anhand dieses Zertifikates praktisch unmöglich machte.
Mit der Übernahme des Box-Zertifikates auch für den FTP-Server (der basiert auf dem "ftpd" aus den GNU-Inetutils) hatte AVM aber nun ein Problem (das war auch der eigentliche Grund, warum vorher das Zertifikat stets neu generiert wurde, wenn man dem Kommentar in einer Quelltext-Datei glauben will) - irgendwie mußte der FTP-Daemon in die Lage versetzt werden, das Kennwort für die Entschlüsselung des "private key" zu erfahren, ohne daß man in dessen Quelltext den Aufruf von "securestore_get" einbaut, da dann wieder die GPLv2-Lizenz die Veröffentlichung der Quellen von "libboxlib" erforderlich machen würde. Also wurde das Tool "getprivkeypass" erfunden ...
Dieses kleine Tool bemüht sich nun (im Rahmen seiner Möglichkeiten) bei seinem Start sicherzustellen, daß es tatsächlich vom "ftpd" aus aufgerufen wurde. Ist das erkennbar nicht der Fall, wird ein (festes) Phantasie-Kennwort zurückgeliefert, mit dem natürlich das Keyfile nicht gelesen werden kann. Für die Identifikation des Elternprozesses liest "getprivkeypass" dazu den Inhalt von /proc/$(ppid)/cmdline und /proc/$(ppid)/stat aus und versucht in den gelesenen Daten die Zeichenkette ftpd zu finden. Wenn das erfolgreich ist, reicht das schon als "Beweis", daß der Aufruf aus dem "ftpd" heraus erfolgte und "getprivkeypass" ruft nun "securestore_get" für uns auf. Nach ein wenig Voodoo mit ein paar Bitknipsereien (das macht auch "securestore_get" schon intern ähnlich) rückt "getprivkeypass" aber dann einen Wert heraus, den man mit geeigneten Mitteln (wie, kann man in den Quellen des "ftpd" ja nachlesen) wieder in ein ordentliches Kennwort (8 Zeichen feste Länge zur Zeit) verwandeln kann. Mit diesem Kennwort kann man dann auch den privaten Schlüssel für andere Programme benutzen.
Um also "getprivkeypass" zu "mißbrauchen", benötigt man nichts weiter als ein paar Zeilen C-Code und einen Programmnamen, der irgendwo (der Test erfolgt derzeit mit strstr) die Zeichenfolge "ftpd" enthält. Dazu habe ich ein kleines C-Programm geschrieben, das in nicht allzu ferner Zukunft in einem weiteren Beitrag (und dann sicherlich auch als Vorschlag für ein "enhancement" im Freetz-Trac) auftauchen wird. Damit kann man dann auch einen Apache2-Server (Direktive "SSLPassPhraseDialog") mit dem Box-Zertifikat "füttern" oder meinetwegen auch das Box-Zertifikat (nach entsprechender Umwandlung) für einen Dropbear-SSH-Server auf der Box verwenden. Aber dieses Programm ist hier eigentlich gar nicht das Thema, dieser Ausflug sollte nur die Notwendigkeit und die Möglichkeiten eines solchen "Proxy-Programms" verdeutlichen, mit dem man "getprivkeypass" zur Herausgabe "überreden" kann.
Denn bei dem, was ich eigentlich mit dem statisch gelinkten "shellinaboxd"-Binary erreichen will, wäre die Notwendigkeit eines weiteren Programms ja wenig hilfreich. Also habe ich in meinen Patch für "ShellInABox 2.14" auch noch den Code aufgenommen, um direkt das "getprivkeypass"-Binary aufzurufen, wenn es vorhanden und ausführbar ist und wenn die o.a. Voraussetzungen für das "Verwirren" von "getprivkeypass" auch vorliegen (also der Name des ShellInABox-Daemons irgendwo "ftpd" enthält).
Der Patch im
1. Die Angabe von "--cert-from-box" erfolgt in einer Form, daß nach der Option gleich noch das Kennwort für den privaten Schlüssel angegeben wird (also "--cert-from-box=boxpassword"). Dann wird genau dieses angegebene Kennwort verwendet, wie das vorher ermittelt wurde, interessiert natürlich nicht. Nachteilig ist es aber weiterhin, daß dann das Kennwort während der gesamten Laufzeit des "shellinaboxd" an diversen Stellen auch abgegriffen werden kann (zu dieser Problematik, von Environment bis /proc/self/cmdline und den jeweiligen Vor- und Nachteilen, gibt es andere ausführlichere Quellen).
2. Es wird kein Kennwort mit der Option "--cert-from-box" festgelegt. Dann prüft der zusätzliche Code als erstes, ob irgendwo im Namen des Programms "ftpd" enthalten ist. Wenn "ftpd" gefunden wird, wird direkt "getprivkeypass" aufgerufen (wenn das Tool auch noch gefunden wird und ausführbar ist), dann braucht es keine weiteren Programme und damit existieren keine weiteren Abhängigkeiten (bei meiner statisch gelinkten Variante). Der Aufruf kann natürlich auch über einen Symlink erfolgen, der den benötigten Aufbau hat ... ich verwende zum Beispiel den Namen "ftpd_siab" für einen Symlink auf "shellinaboxd", damit kommen keine Unklarheiten auf, was sich hinter dem Namen eigentlich verbirgt.
3. Übrig bleibt noch die Form, bei der weder das Kennwort beim Aufruf angegeben wurde noch der Dateiname ein "ftpd" irgendwo enthält. Dann versucht der Code über die Environment-Variable "KEYPASSWORDPROXY" einen Programmnamen für den oben beschriebenen "Proxy" zu lesen und diesen aufzurufen (wieder nach einem Test, ob die Datei existiert und ausführbar ist), um an das Kennwort zu gelangen. Das ist dann zumindest wieder eine Variante, bei der das Kennwort nicht permanent irgendwo im Speicher liegt wie bei Variante 1.
Wenn Box-Key und -Zertifikat nicht gelesen werden können, verweigert der zusätzliche Code bei Angabe von "--cert-from-box" die Arbeit, es wird also auch kein neues Zertifikat für SIAB automatisch generiert.
Ob ich das irgendwann als Patch im Freetz-Trac einreiche, weiß ich noch nicht so genau. Es ist für AVM ja ein Leichtes, den bisher arg blauäugigen Test auf "ftpd" zu verschärfen oder sich wieder etwas Neues einfallen zu lassen, um "getprivkeypass" irgendwie zu ersetzen. Das macht meine Lösung stark vom derzeitigen Stand (gilt von 06.20 bis 06.24) abhängig, falls AVM da irgendetwas dagegen haben sollte. Mir fällt zwar auch nicht ein, was das sein sollte (es spricht für mich deutlich mehr dafür, das Box-Zertifikat mehrfach zu verwenden anstatt es mehrfach an verschiedenen Stellen auf der Box zu speichern), aber man kann ja nie wissen ... ich habe auch absichtlich "nur" den Weg über "getprivkeypass" gewählt und den Aufruf von "securestore_get" außen vor gelassen. Aber ein simples Disassemblieren von "getprivkeypass" reicht ja schon aus, um auch dort die notwendigen Voraussetzungen für den Aufruf zu erkunden. Da das auch die "bad guys" machen könn(t)en, sehe ich die Sicherheit nicht beeinträchtigt.
Wenn man auf der Box ein verschlüsseltes Zertifikat speichert (das ist grundsätzlich auch richtig so in meinen Augen, damit da kein Mißverständnis entsteht) und das muß für die Verwendung automatisch entschlüsselt werden, dann braucht es eben auch einen Weg, das zu tun. Da beißt die Maus keinen Faden ab und wenn damit der private Schlüssel etwas weniger "vertrauenswürdig" ist, muß man das eben beim Umgang mit solchen Verbindungen berücksichtigen. Da kann AVM auch wenig bis nichts dagegen tun ... wer es anders und sicherer haben will, braucht eine Art TPM per USB o.ä. angebunden - das ist dann sogar in meinen Augen für ein Consumer-Gerät eher Overkill, solange solche Teile nicht irgendwo in den Prozessoren direkt eingebaut sind und nur noch benutzt werden müssen.
Zuletzt bearbeitet: