---
# System prepended metadata

title: Audit des logiciels SomeClient.exe et SomeServer.exe

---

# Audit des logiciels SomeClient.exe et SomeServer.exe
Le but de ce rapport est de réaliser un audit des logiciels SomeClient.exe et SomeServer.exe et de voir si ces logiciels présentent des vulnérabilités importantes au point d'impacter la sécurité des utilisateurs.
## Contexte de l'audit
Le but de cette section est d'expliquer le contexte de l'audit. Cela comprend le but des logiciels testé, leur fonctionnement ainsi que les conditions dans lequels ils furent audités. 
### But des logiciels SomeClient.exe et SomeServer.exe
Cet ensemble de logiciel a été mise au point par la société SomeSoftware. Leur but est d'offrir un service d'hébergement des données avec un client. Le logiciel du serveur (SomeServer.exe) offre la possibilité à quiconque qui se connecte dessus avec le logiciel client dédié (SomeClient.exe) de téléverser des fichiers dessus. Il propose un fonctionnement similaire au protocole réseau FTP (File Transfer Protocol) dans son utilisation. Il offre également un système de permissions pour restreindre l'accès à certaines ressources selon l'accréditation de l'utilisateur connecté. Voici d'ailleurs l'interface de connexion du logiciel client : 
![](https://i.imgur.com/5em5ekE.png)
Et un exemple d'utilisation une fois que l'utilisateur est connecté au serveur : 
![](https://i.imgur.com/pAdgCgg.png)
Maintenant, nous allons voir comment ces deux logiciels fonctionnent ensemble techniquement parlant. 
### Schéma d'architecture des logiciels SomeClient.exe et SomeServer.exe
Avant de commencer l'audit, voici un schéma qui explique le fonctionnement des logiciels SomeClient.exe et SomeServer.exe : 

![](https://i.imgur.com/e3Xs4Tj.png)

1) Le client se connecte au serveur. Par défaut ce dernier est en écoute sur le port 4444. il peut s'authentifier en mode "Basic Authentication" ou bien en utilisant le certificat du serveur. 
2) Le serveur, si les identifiants soumis par le client sont valides, envoie au client, les données contenues dans la base de données, à savoir la liste des fichiers présents.
3) A partir de cette étape, le client peut, selon ses accréditations, téléverser, modifier où changer les droits d'accès d'un fichier. Il peut également créer un répertoire et naviguer dans les dossiers du serveur.
4) Une fois qu'il a fini, le client peut se déconnecter du serveur pour fermer la connexion.

Notez ici que le serveur peut fonctionner de deux façons différentes. Il peut être exécuté à la main avec l'aide d'un terminal de commande ou bien être installé sur la machine. S'il est installé sur la machine, cela veut dire qu'il sera lancé par défaut au démarrage du serveur Windows. La capture d'écran de la fonction (renommé installSomeServer) montre la façon dont le logiciel du serveur s'installe sur l'ordinateur : 

![](https://i.imgur.com/j5uTJDe.png)

Nous pouvons voir ici qu'une valeur est créé dans ce chemin de registre : 
'SYSTEM\CurrentControlSet\services\eventlog\Application\SomeServer'
De plus, le processus chargé de démarrer le serveur aura pour nom, "SomeServer".

### Les conditions mises en place pour l'audit
Pour mener à bien cette audit, nous avons créé les utilisateurs suivants que nous utiliserons au cours de nos scénarios : 
- test:password1 (Accrédité "Public")
- employe:password2 (Accrédité "Restreint")
- chef:password3 (Accrédité "Confidentiel")
- manitou:password4 (Accrédité "Secret")
- supermanitou:password5 (Accrédité "Top Secret", il possède également le rôle d'administrateur sur le serveur)

Enfin, nous avons également créé puis téléversé les fichiers et dossiers suivants sur le serveur :
#### Fichiers présent sur le serveur 
- fichier_public.txt (Classifié "Public")
- fichier_restreint.txt (Classifié "Restreint")
- fichier_confidentiel.txt (Classifié "Confidentiel")
- fichier_secret.txt (Classifié "Secret")
- fichier_top_secret.txt (Classifié "Top Secret")
#### Dossiers présent sur le serveur
- Public (Classifié "Public")
- Restreint (Classifié "Restreint")
- Confidentiel (Classifié "Confidentiel")
- Secret (Classifié "Secret")
- Top Secret (Classifié "Top Secret")

Tout cela nous permettra de tester les deux logiciels au cours des différents scénarios proposés ci-dessous. 
## 1er scénario : Authentification des utilisateurs en mode "Basic Authentication"
Au cours de ce scénario, nous allons voir s'il est possible d'obtenir les identifiants d'un utilisateur lorsque ce dernier cherche à se connecter au serveur en mode "Basic Authentication" (Sous réserve qu'un attaquant puisse enregistrer l'activité réseau au moment d'une connexion). 


### Analyse de paquets via Wireshark
Nous avons capturé avec Wireshark, l'ensemble des paquets réseaux transitant entre le client et le serveur au moment où un utilisateur se connecte. En mode "Basic Authentication", nous avons pu constaté que les identifiants ne circulent pas en clair. Nous allons quand même voir s'il n'est pas possible à tout hasard d'obtenir malgré tout les informations envoyées par l'utilisateur au serveur. 

### Analyse du processus de chiffrement des données sur le client via IDA

Premièrement, on utilise le logiciel "Resource Hacker" afin d'identifier les différents champs composant l'interface du logiciel client.
![](https://i.imgur.com/AKT2O3r.jpg)

On remarque que l'ID 1002 correspond à l'input dans "Nom d'utilisateur" tandis que l'ID 1003 correspond à l'input "Mot de passe"
 
On recherche donc la fonction permettant de récupérer le titre où le texte associé à un `control` dans un dialog box. Il s'agit de `GetDlgItemTextA`.
 
![](https://i.imgur.com/Raa61bp.png)
 
Ensuite on recherche les occurences de `GetDlgItemTextA` et on trouve rapidement la partie où le `control` 1002 est utilisé, c'est-à-dire le champ "Nom d'utilisateur".
![](https://i.imgur.com/pMWzxwR.png)
 
Enfin, on peut créer des "enums" afin de mapper des valeurs numériques avec des noms plus parlant pour ajouter de la sémantique et simplifier la compréhension du code. Au lieu d'avoir des valeurs numériques, on aura donc directement le nom de l'élément auquel il fait référence. 
![](https://i.imgur.com/LcBYmUP.png)
 
Ensuite on revient sur la vue assembleur, on sélectionne la valeur des ID à mapper, on appuie sur la touche `m` et on choisit l'enum à mapper. Dans le cas de l'ID `1002`, on mappera `ID_EDIT_USERNAME`.

Par la suite, nous remarquons que l'adresse de l'username est stocké dans le registre `edi`. Tandis que l'adresse du mot de passe est stocké dans eax et correspond à `edi+0x80`.

Ainsi, nous allons créer une structure accueillant les deux variables d'une taille de `0x80`.
![](https://i.imgur.com/WqCEUFC.jpg)

Pour ce faire, une fois la structure créée, nous avons appuyer sur `d` afin de créer une variable puis sur `*` afin de modifier sa taille à `0x80`. Enfin on la renomme avec `n`.

On revient ensuite sur la vue assembleur afin de se rendre sur l'adresse de `ID_EDIT_PASSWORD`, on sélectionne `0x80` et on appuie sur `t` afin de référencer l'adresse de la variable `context_t.password`. 

On parcourt ensuite la suite du programme et on retrouve un autre appel à notre mot de passe. Celui-ci est poussé sur la pile et une fonction est appelée ensuite.
![](https://i.imgur.com/hcOb3xv.png)

Ensuite on redéfinit avec `y` la fonction `sub_44D950`. À cette étape, nous formulons une hypothèse: il s'agirait d'un `thiscall` car `ecx` est toujours passé en paramètre pour cette convention d'appel, il contient un pointeur sur un objet.
![](https://i.imgur.com/rUcZIIQ.png)

En effet on remarque qu'à l'origine, la déclaration de la fonction est la suivante :
`int __stdcall sub_44D950(int, int, int);`

On modifie donc alors la définition de la fonction de cette façon :
`int __thiscall sub_44D950(void *this, void *, char *username, char *password);`

Effectivement, l'instruction `push ecx` correspond bien au mot de passe et l'instruction `push edi` au nom d'utilisateur et ainsi de suite.

Ensuite on se rend dans la fonction en question, on remarque que `ecx` est déplacé dans `esi`. Plus tard, un offset est déplacé dans le registre `esi` correspondant à notre objet. L'offset correspond finalement à la vtable de l'objet.
![](https://i.imgur.com/rSRImBG.png)

En regardant dans les RTTI, on remarque plusieurs méthodes virtuelles. Il s'agit d'un tableau de pointeurs de fonctions, soit notre "vtable".
![](https://i.imgur.com/6sFRDGU.png)

![](https://i.imgur.com/htzViSn.png)

On remarque une méthode `SockerClientEncrypted` :
![](https://i.imgur.com/VAilAER.png)

Afin de comprendre le code, on créé une structure `SocketClientEncrypted` dans la quelle on ajoute la vtable, l'username et le password. Pour rappel, la "vtable" définit les méthodes virtuelles utilisées.

Avant de créer cette structure, nous devons connaître la taille qui lui est allouée. En revenant en arrière, on remarque l'appel de la fonction `new` pour laquelle on pousse une taille de 234 octets.
![](https://i.imgur.com/MMYxvxm.png)


Nous crééons donc une structure `SocketClientChiffre` de taille `0x234`. Le premier paramètre est donc un pointeur vers la vtable.
![](https://i.imgur.com/w6EQU4v.png)

On revient sur la vue assembleur et on remarque qu'aux offsets `+18` et `+1C` sont respectivement attribués les pointeurs vers `username` et `password`. Nous avons donc créés ces deux valeurs dans notre structure.
![](https://i.imgur.com/MxxRL3O.png)

Ensuite, une fonction est appelée, lorsque l'on entre dedans on remarque que des constantes sont utilisées.
![](https://i.imgur.com/HaEKwpa.png)

Avec un peu de recherche, on apprend que ces constances sont appelées dans la fonction `rand` .https://en.wikipedia.org/wiki/Linear_congruential_generator.

La fonction `rand` comme son nom l'indique, permet d'obtenir un nombre aléatoire.

Ensuite, on remarque qu'une fonction `memset` est appelée afin d'allouer un espace mémoire de 256 bits dans `eax` avec la valeur `0`. Sachant que `eax` pointait vers l'offset `0x2C` de `SocketClientEncrypted`
![](https://i.imgur.com/C6LKtlJ.png)

Ensuite, nous remarquons que 3 autres variables de 4 octets sont initalisées ainsi qu'une nouvelle variable de 256 bits:
![](https://i.imgur.com/MyvVKrk.png)

Pour finir, à l'offset 230 nous avons une nouvelle variable:
![](https://i.imgur.com/4PDl2Hq.png)

Maintenant que nous avons vu comment les informations de l'utilisateur sont traités par le logiciel client, nous allons voir comment ce dernier initialise la connexion avec le serveur distant. 
### Send Hello ou initier la connexion avec le serveur
En entrant dans la vtable `SocketClientEncrypted` la première méthode virtuelle est `Connect`. Il semblerait qu'il s'agisse d'une initiation de connexion vers le serveur dans l'attente d'une réponse.

Ensuite, la fonction `SendHello` contient une instruction permettant d'affecter dans un registre la valeur `SomeClient v1.0.0`.
![](https://i.imgur.com/XgcyT74.png)

En lançant Wireshark, on observe que lorsque le paquet `Hello` est transmis, le client envoie la chaîne de caractères "SomeClient v1.0.0".

Une fois que la connexion est initialisé avec le serveur, nous allons voir comment le client et le serveur s'échangent les données nécessaire à la génération d'une clef de chiffrement. 
### Envoi de la Seed au serveur
Après la fonction `SendHello`, on remarque une nouvelle fonction prenant en paramètre:
- un entier ayant pour valeur 6
- l'objet SocketClientEncrypted pointé par ecx (thiscall)
- et un pointeur

![](https://i.imgur.com/ZWnJsvj.png)

Rapidement, la fonction `send` de l'API Windows attire notre attention. Celle-ci prend en paramètres:
- un pointeur vers une socket
- un pointeur vers un buffer
- une taille

On crée donc une entrée `socket` dans notre sructure `socketClientChiffre`à l'offset `04`. Ensuite, on retype la fonction de la manière suivante:
`int __thiscall envoyerSeedPacket(socketClientChiffre *socket, char *buffer, int size);`

De plus, en regardant les paquets transmis dans Wireshark, nous remarquons que le second paquet envoyé par le client a des données d'une taille de 6 octets. 

![](https://i.imgur.com/ZoOn2r9.png)

Ici, la seed vaut donc `0x4573` comme nous sommes en little endian.
Cette valeur est importante puisqu'elle sera utilisé par le client et le serveur pour la génération d'une clef de chiffrement. D'ailleurs, nous allons voir comment les données venant du serveur sont réceptionnées par le client. 
### Réception des données venant du serveur
Ensuite, on observe une nouvelle fonction prenant en paramètres:
- un entier ayant pour valeur 8
- un pointeur vers un buffer
- un pointeur vers un socket

![](https://i.imgur.com/GrGjkWF.png)

Nous comprenons donc que cette fonction permet de recevoir la réponse du serveur. Afin de confirmer cette hypothèse, nous rentrons dans la fonction et remarquons un appel à une autre fonction de l'API Windows, `recv`.

Cette fonction prend les mêmes paramètres que la fonction `send`. Ainsi on en déduit que la réponse du serveur a pour taille, 8 octets. Elle est stockée dans le buffer.

Ensuite, pour connaître le contenu de la réponse du serveur, nous nous penchons sur les instructions suivantes. En effet, la réponse est déplacée dans `eax` puis dans un champ de notre objet que nous ne connaissons pas encore.

![](https://i.imgur.com/Q5IU1xs.png)

Nous le verrons dans la partie suivante, mais il s'agit d'une seconde seed.

Cette fois nous cherchons un paquet dont les données font 8 octets. Et deux paquets après l'envoi de la seed par le client, nous trouvons la réponse.

![](https://i.imgur.com/j9Azxxy.png)

Ainsi la seed vaut `0x29`.

### Création des clés de chiffrement
![](https://i.imgur.com/rDpeV8k.png)
![](https://i.imgur.com/FZIpb3A.png)

Nous savons qu'il s'agit d'une fonction `srand` car elle prend en paramètre notre seed et est appelée avant un `rand`.

La fonction `srand` permet d'initialiser la valeur de départ de la fonction `rand`.

Ensuite, nous rentrons dans une boucle permettant de prendre le premier octet du nombre aléatoire généré par le `rand` puis le déplace dans un champ de notre objet de taille `256`. Ainsi on itère sur le nombre aléatoire jusqu'à remplir le champ.

Le même processus est réalisé à la suite mais à un offset différent de notre objet, il s'agit d'une seconde seed. Puis chaque octet du nombre aléatoire constitue une nouvelle clé. Nous avons créé les valeurs correspondantes dans notre structure et les avons renommées.

![](https://i.imgur.com/OMsCUG8.png)

Nous savons désormais que la première fonction établit un canal de communication avec le serveur et échange les seed. Maintenant, nous allons voir le mécanisme utilisé par le client et le serveur pour sécuriser l'authentification d'un utilisateur. 

### Authentification de l'utilisateur auprès du serveur
Nous analysons maintenant la fonction appelée après connect. Celle-ci est une nouvelle fois un `thiscall`car elle prend en paramètre l'objet this via`ecx`.

![](https://i.imgur.com/VySeybR.png)

Ensuite, on remarque que la fonction s'alloue `0x80` octets de mémoire.

![](https://i.imgur.com/NR7riHI.png)

Juste après, la fonction utilise deux fois `strncpy` pour copier deux buffer de taille `0x40` octets. Il s'agit du nom d'utilisateur et du mot de passe. Mais également une variable valant 2 octets est créée à l'offset `0x2`.

![](https://i.imgur.com/g7fm30w.png)


De plus, une nouvelle fonction est appelée via la vtable de l'objet et prends en paramètres:
- Un entier `0x82`
- L'adresse contenant le word valant 2
- L'objet SocketClientEncrypted via `ecx`

Il paraît évident que la fonction va traiter les champs "Nom d'utilisateur" et "Mot de passe". Soit `0x80` + `0x2`. Mais aussi, la taille du paquet envoyé par le client après l'échange des seeds est de `0x82`.

Ensuite, la fonction `send` est appelée, nous allons entrer dedans.

![](https://i.imgur.com/Mvy0Z38.png)

Ci-dessous, nous remarquons qu'une variable permettant de définir à quel  offset de la clé nous sommes est chargée dans `edx`. Cela signifie que pour un paquet de taille n chiffré, le paquet suivant commencera à chiffrer avec l'octet n+1 de la clé.

![](https://i.imgur.com/R2uvSxb.png)

De plus, la suite du code nous indique que chaque octet du message subit une opération binaire de type "XOR" avec un octet de la clé. Le résultat est déposé dans l'espace mémoire alloué au début de la fonction.
![](https://i.imgur.com/e9o1o0x.png)


Les données chiffrées sont ensuite envoyés au serveur. Nous pouvons désormais tenter de réimplémenter le mécanisme de chiffrement pour déchiffrer la capture réseau qui nous a été fourni.

## Réimplémentation
Afin de déchiffrer les données capturées dans Wireshark, nous avons copié le chiffré susceptible de contenir le mot de passe ainsi que le nom de l'utilisateur. Nous l'avons ensuite placé dans ce programme qui réimplémente en C++, le mécanisme de chiffrement utilisé par le client et le serveur :
```c++
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <format>

using namespace std;

int main()
{
    srand(0x4573);
    string cipher = "f394dcbdda0cf729de14e5c61584910e9c12bb4fd99d987d3edcd3286ff2d1aca74339a85885b4b1111af147a59ded078abb71237f44dc107181227ea0c9158dfe4fa6708477a274cc5fb500e5a5deda92700ef66b69a7f14d8c02ecc8f78f0bbd61bd8681b905f59885ad1d08c5831ebbc866ed2444070526a6f15a31a7c78fae20"; // Contenu extrait de la trame fourni qui contient le login et mot de passe de l'utilisateur à trouver
    string key;
    for(int i = 0; i < 256; i++)
    {
        int k = rand();
        key += std::format("{:02x}", k%256);
    }
    
    string res = "";
    for(int i = 0; i < cipher.length(); i+=2)
    {
        res += (char)(stoi(cipher.substr(i,2),nullptr,16) ^ stoi(key.substr(i,2),nullptr,16));
    }
    cout << res << endl;
    return 0;
}
```
Afin de compiler et exécuter ce code, voici les instructions à suivre:
```
cl /EHsc script.cpp
script
```

Nous l'avonc compilé et exécuter à travers Visual Studio Code, voici le résultat:
```
PS C:\Users\emile\Documents>  & 'c:\Users\emile\.vscode\extensions\ms-vscode.cpptools-1.12.4-win32-ia32\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-q3ywy3gi.yjb' '--stdout=Microsoft-MIEngine-Out-gt1trhol.f4y' '--stderr=Microsoft-MIEngine-Error-1jql3toi.4bt' '--pid=Microsoft-MIEngine-Pid-wykhel3l.35n' '--dbgExe=C:\msys64\mingw64\bin\gdb.exe' '--interpreter=mi'
jackENSIBS{W3ll_d0ne_C@pt41n}
```

### Les recommandations à appliquer

Nous avons pu constaté ici que le logiciel, lorsqu'on utilise le mode "Basic Authentication", est vulnérable à une écoute passive du réseau par un attaquant. Pour mitiger le risque lié à cette vulnérabilité, il est recommandé d'appliquer les mesures suivantes : 
- S'assurer que le lien réseau reliant le client au serveur est sécurisé et ne fait pas l'objet d'une écoute quelconque.
- Attendre une mise à jour des développeurs pour qu'ils corrigent la vulnérabilité.  

Nous allons maintenant passer au 2ème scénario pour tester les permissions d'accès aux fichiers et répertoires présents sur le serveur. 
 ## 2ème scénario : Les permissions d'accès aux fichiers et répertoires
Au cours de ce scénario, nous allons chercher à voir s'il est possible de contourner les permissions d'accès mises en place. En d'autres termes, voir si un utilisateur possédant une accréditation "Restreinte" peut avoir accès à des fichiers au moins classifiés "Confidentiel" par exemple. L'entiéreté de ce scénario sera réalisé à partir du compte "employé" qui est seulement accrédité pour accéder aux données dites "Restreinte".

### Vérification des permissions d'accès aux fichiers et répertoires

Pour vérifier cela, nous allons nous connecter au serveur avec le compte "employé" :
![](https://i.imgur.com/KPXRrla.png)

Maintenant que nous sommes connectés, nous avons pouvons voir l'ensemble des fichiers disponible sur le serveur : 

![](https://i.imgur.com/hNHgJPH.png)

Nous arrivons sur ce menu, un fichier retient rapidement notre attention, il s'agit du fichier nommé "fichier_top_secret.txt" classifié "Top Secret" : 

![](https://i.imgur.com/AAgyVu0.png)

Etant connecté sous l'identité "employe", je ne devrais pas être en mesure de le télécharger. Essayons quand même de le faire. 

![](https://i.imgur.com/A47D7Kd.png)

J'ai pu télécharger le fichier sans message d'erreur comme le montre cette capture d'écran des logs du serveur : 
![](https://i.imgur.com/eAh1Nci.png)
En ce qui concerne le fichier ? J'ai bien réussi à récupérer son contenu : 

![](https://i.imgur.com/tdCqjKY.png)


Tant qu'on y est, je peux modifier les permissions d'accès des fichiers sans que le serveur me bloque, faute de privilèges suffisants. L'ensemble de ces actions furent réalisés avec le compte "employé" : 

![](https://i.imgur.com/XbTvxDI.png)

Comme le montre les logs du serveur, tout s'est bien passé sans la moindre erreur : 

![](https://i.imgur.com/97eXP2S.png)

Alors pourquoi le serveur accepte sans problème toutes ces requêtes sur des fichiers auquel le compte "employé" n'est pas censé avoir accès ? Nous allons essayer de voir cela ensemble.

Si l'on analyse le code-source du logiciel client, on constate qu'il existe bien des messages qui sont prévus par le développeur pour avertir l'utilisateur qu'il ne peut pas réaliser certaines actions faute des autorisations suffisantes : 

![](https://i.imgur.com/aBqqZAC.png)

Toutefois, on peut supposer ici (au vue de la fonction qui fut renommé "erreurIdentification") que le client ne fait qu'interpréter le code de retour renvoyé par le serveur. Cela signifie alors que le problème se situe du côté du serveur et non du côté du client. Pour s'en assurer, allons jeter un coup d'oeil sur le code-source du serveur : 

![](https://i.imgur.com/GwuLgt3.png)

Voici un extrait du code source en assembleur du serveur où il gère les requêtes du client lorsque ce dernier souhaite télécharger un fichier. Au vue des lignes de codes présentes, nous pouvons voir la fonction qui, selon nous, permet de gérer les différentes erreurs qui seront renvoyés au client. Les erreurs peuvent être de toute nature. Voici d'ailleurs la fonction qui permet de renvoyer un code d'erreur au client : 

![](https://i.imgur.com/WkKYp02.png)

Nous ne sommes pas parvenus à identifier le bloc d'instructions censé avertir le client qu'il n'a pas les autorisations pour réaliser certaines actions. Selon nous, il existe différentes théories qui peuvent expliquer la raison de ce bogue : 

- Il n'existe pas de fonction permettant de vérifier les permissions de l'utilisateur connecté
- La fonction qui vérifie les permissions du compte client est bien implémenté mais aucune instruction au sein du serveur y fait référence d'une façon ou d'une autre. 

Pour lever le doute ici, il faudra faire appel à un analyse plus expérimenté.


### Les recommandations à appliquer pour utiliser au mieux ce logiciel

En raison de la nature préoccupante de cette faille de sécurité, nous considérons qu'il n'est pas sûr d'utiliser ce produit pour héberger des données ayant une classification supérieure ou égale à "Restreinte". Voici alors les recommandations à appliquer en cas d'adoption de ce logiciel : 

- Ne pas stocker de données classifiés à partir de "Restreinte".
- Attendre une mise à jour des développeurs pour corriger ce problème.

Nous n'avons pas de preuve de concept à vous proposer pour ce scénario, vous avez juste besoin d'un identifiant et mot de passe valide et vous aurez accès à l'ensemble des fichiers, peu importe votre niveau d'accréditation et la classification des fichiers présents sur le serveur. 


## Liste des problèmes rencontrés au cours de notre audit 
Non seulement nous avons pu constater au cours des différents scénarios que ce logiciel était vulnérable mais il comporte également un ensemble de problème. Il est important pour les développeurs de ce produit de corriger au plus vite ce que nous avons pu relever.
### Impossibilité de téléverser un fichier dans un dossier
Le logiciel offre la possibilité de créer sur le serveur distant des répertoires pour qu'on puisse y stocker nos fichiers. Or, lorsqu'on crée un dossier puis qu'on téléverse un fichier dedans, voici le message d'erreur que l'on obtient : 

![](https://i.imgur.com/5LZxiTB.png)


Le logiciel client plante et doit être fermé. Nous considérons que ce problème rencontré au cours de l'audit est suffisamment important au point d'entraver l'usage normal de ce produit. Nous recommandons ici d'attendre une mise à jour des développeurs pour qu'ils corrigent ce problème.
### Le port d'écoute du serveur distant

Nous avons pu constater au cours de notre audit que le serveur écoute par défaut sur le port 4444. Ce numéro de port réseau est le même qui est utilisé par Metasploit par défaut pour lançer des attaques à travers les réseaux informatique. Cela veut dire que le trafic réseau échangé entre le client et le serveur peut être confondu avec une tentative de piratage informatique. Afin d'éviter d'alerter inutilement le SOC de toute entité souhaitant utiliser le produit, il est recommandé aux techniciens chargés du déploiement de changer avant tout démarrage du logiciel, le port d'écoute du serveur.

### Les transferts de fichiers

Au cours de cet audit, nous nous sommes intéressés à la façon dont les fichiers sont transférés entre le client et le serveur. Pour cela, nous avons téléversé un fichier sur le serveur à des fins de test (flag.jpg). 

![](https://i.imgur.com/BJp7YL2.png)

On suppose ici que le programme, pour envoyer un fichier au serveur, fait appel à la fonction "readFile". Lorsqu'on cherche toutes les occurrences de cette dernière, on tombe assez rapidement sur la fonction qui gère l'interface permettant de créer un répertoire, supprimer un fichier, ajouter un fichier... Nous parvenons alors à voir la fonction suivante qui gère l'affichage de la fenêtre du côté du client : 

![](https://i.imgur.com/jq1e4v8.png)

Après quelques tests, on identifie la partie du code qui s'occupe du fichier pour le transférer au serveur : 

![](https://i.imgur.com/cjRBsRM.png)

Nous pouvons y voir une allocation de mémoire pour prendre le contenu du fichier ainsi que l'appel d'une fonction pour ouvrir le fichier de notre choix. 

Cependant, là où cela devient intéressant, c'est que le code utilisé pour lire le contenu du fichier à envoyer se situe ici, dans la fonction "dialogueChoixFichierAEnvoyer" (Renommé par nos soins) : 

![](https://i.imgur.com/LWQiDKr.png)

Nous constatons qu'il fait appel à la fonction "Send" de l'objet SocketClientChiffreVtable pour envoyer le fichier au serveur.

Or, nous avons démontré au cours du premier scénario que la méthode de chiffrement utilisée peut être cassé à condition d'avoir une capture réseau avec dedans, une interaction entre le client et le serveur. 

#### Les recommandations à appliquer

Nous avons pu constaté ici que le logiciel, lorsqu'on utilise le mode "Authentification basique", est vulnérable à une écoute passive du réseau par un attaquant. Cela lui permet de récupérer les identifiants mais également les fichiers transférés au serveur. Pour mitiger le risque lié à cette vulnérabilité, il est recommandé d'appliquer les mesures suivantes : 
- S'assurer que le lien réseau reliant le client au serveur est sécurisé et ne fait pas l'objet d'une écoute quelconque.
- Attendre une mise à jour des développeurs pour qu'ils corrigent la vulnérabilité.

## Conclusion

Nous avons pu, au cours de cet audit, tester les logiciels SomeClient et SomeServer développés par l'entreprise SomeSoftware. Au vu des résultats obtenus, nous conseillons, si cela est possible, d'attendre des mises à jours de la part des développeurs ou bien d'appliquer les recommandations proposées pour sécuriser au mieux l'usage de ce produit. 

## Auteurs de l'audit
L'audit a été réalisé par le groupe N° 8, à savoir Emile MARIÉ (Cyberdef5 TD1/TP1) et Corentin OLLIVIER (Cyberdef5 TD1/TP2).