---
# System prepended metadata

title: Projet Software Security

---

# Projet Software Security

## Phase de spécification

SecTrans est une application de transfert de fichier fonctionnant en mode Client-Serveur. Cette application sera utilisé par les employé de l'entreprise pour envoyer des fichiers de manière securisée sur un serveur qui les stockera. Ils auront aussi la possibilité de recupérer un fichier donné qu'ils ont publié auparavant. Il est important de noter que le serveur sera déployé dans les locaux de l'entreprise et sera accesible aux employés depuis n'importe où grâce à internet.

### Architecture du systeme

Dans le cadre de ce projet nous avons opté pour une architecture Client-Serveur, avec ainsi deux éxecutables, un premier pour le Client, et l'autre pour le Serveur.

Ces 2 exécutables incorporent chacun les deux bibliothèques dynamiques de Macrohard Corporation puisque les clients et le serveur doivent pouvoir recevoir et envoyer des données.

### Menaces possibles

Bien que cette architecture soit efficace, elle présente la faiblesse que les clients posséderont directement un exécutable leur permettant de communiquer avec le serveur, plutôt que d'avoir une interface entre les clients et la partie "interne" du système. De plus comme spécifié dans l'énoncé, ce framework n'inclus aucun mécanisme de sécurité par défaut, chose que nous devons absolument prendre en compte. 
Parmis les principales menaces qui pèsent sur nous, on retrouve : 

- **La transmission non sécurisée des données**, l'absence de mécanismes de sécurité dans le framework Macrohard expose les données lors de leur transmission entre le client et le serveur, un attaquant pourrait écouter sur le canal de transmission et récupérer des données transmises du client vers le serveur et inversement.

- **La gestion des accès**, des utilisateurs non autorisés pourraient tenter d'accéder au serveur, d'envoyer des fichiers corrompus au serveur ou récupérer des fichiers qui ne sont pas les siens, compromettant ainsi la confidentialité et l'intégrité des données stockées ou même le serveur en lui même.

- **Le manque de confidentialité des fichiers stockés**, ces derniers pourraient être accessibles à des personnes non autorisées. Si un attaquant arrive a s'introduire sur le serveur et que les fichiers ne sont pas chiffrés, il peut facilement récuperer les differents fichiers.

- **Des attaques DDoS** pourraient compromettre la disponibilité du service (surtout côté serveur centralisé), entraînant des pannes, des temps d'arrêt et des coupures au milieu d'échanges.
- Vis-à-vis de la bibliotheques, il faut aussi tenir compte de la **gestion des erreurs inefficace** qui pourrait fournir des informations sensibles aux attaquants.
- Le manque d'obfuscation de code, en effet nous avons pus facilement decompiler les codes des librairies et ainsi connaitre leur implémentation

Donc au total nous retrouvons **6 Menaces principales**. Dans les parties suivantes nous allons vous expliquer plus en détail les risques de ces menaces et expliquer notre approche pour le developpement securisé de ce logiciel.

## Implementation de Macrohard

Même si aucun mécanisme de sécurité est implémenter, il est essentiel de connaitre l'implémentation de ces bibliotheques pour cerner d'eventuelles failles de type buffer overflow ou des erreurs mal gérées.

Donc un premier travail de rétro-ingenierie a été fait sur le framework, le résultat des fichiers décompilés fournis par IDA et dogbolt est disponible sur le rendu

### libclient.so

Elle ne comporte qu'une fonction, **sndmsg** qui envoi un message passé en parametre, à un port lui aussi passé en parametres.

On remarque que cette fonction utillise des fonctions comme ``strncpy()`` pour copier le message passé en argument. Cependant, cela ne garanti pas la null-termination de la chaîne, ce qui pourrait conduire à des comportements inattendus.

Ensuite, nous avons la création et l'utilisation de Sockets pour établir une connexion. Dans le cas de notre code cela correspond à la famille des protocoles IPv4 et le type de socket correspond à SOCK_STREAM (socket orientée connexion).  

La fonction essaie de se connecter à une adresse IP spécifique (127.0.0.1) sur un port spécifique donner en parametre

Pour envoyer les données sur le socket elle utilise ``send``, mais ne verifie pas que la taille des données soit correcte ce qui peux causer des overflows

Pour afficher des messages d'erreur dans la console, sndmsg() utilise des ``puts`` ce qui est une source potentielle d'informations sensibles pour un attaquant

Et enfin on a un ``close`` apres l'envoi du message. Cepandant il n'est pas présent dans les cas d'erreur, donc le socket peut rester ouvert en cas d'erreurs imprévues

### libserver.so

Elle comporte 3 fonctions : **startserver**, **getmsg**, **stopserver**

La premiere fonction "startserver" prend en parametre un entier représentant un port et permet de démarrer le serveur
On a cette fois la fonction ``perror`` pour afficher des messages d'erreur dans la console, encore une fois une source potentielle de fuite d'information sur l'implémentation de la librairie. Et comme tout à l'heure, les sockets ne sont pas fermés en cas d'erreur entraînant des fuites de ressources et des problèmes potentiels dans le système.

La deuxieme fonction "getmsg" prend en parametre une chaine de caractere et permet de recevoir des message de taille variable depuis un client 
Pour commencer la fonction copie les données lues depuis le socket avec ``strcpy``, cela peut entrainer un buffer overflow si le contenu du socket est trop grand.
Encore une fois la gestion des erreur avec ``perror`` qui donne des informations sur l'implémentation de la librairie.
Et enfin on remarque encore une fois que, si une erreur survient lors de la lecture depuis le socket, la fonction appelle ``exit(1)`` sans fermer la socket créée précédemment. Entrainant des fuites de ressources et des problèmes potentiels dans le système. 

Enfin pour la derniere fonction "closeserver", rien à signaler pas de probleme de securité a remarqué


### Contre-rendu

A travers cette rétro-ingenierie il y'a 3 principales faiblesses à prendre en compte lié a l'implémentation des libriaries : 

- Les buffers overflows possibles liés à l'utilisation de strcpy
- Les socket non fermes en cas d'erreur
- Les messages d'erreur console qui donne des indications sur l'implémentation des librairies

## Implémentation Securisé

Aprés cette phase d'analyse des risques, nous avons commencé par implémenter les differentes fonctionalités du logiciel : 

- sectrans -up
- sectrans -down
- sectrans -list

Pour ce faire nous avons mis en place une architecture sécurisée grace aux respects de certaines regles de programmation. 

Nous avons utilisé une approche modulaire, chaque fichier a ses propres responsabilités, elle y est ainsi plus facile à sécuriser puisqu'il suffit de sécuriser chaque petit "module" pour sécuriser l'ensemble du logiciel. Et de plus l'approche modulaire facilite la mise en œuvre de fonctionnalités de sécurité spécifiques dans des modules dédiés.

Tout d'abord nous avons fait attention de ne pas utiliser, si possible, des fonctions de manipulation de chaînes de caractères qui ne vérifient pas correctement la longueur des chaînes telles que ``Gets()`` ou ``strcpy``, nous préférons utiliser des primitives plus sécurisées, qui vont limiter la quantité de données copiées, comme par exemple ``strncpy()``. Ces mesures visent à limiter et à prévenir les attaques de corruptions de mémoires comme le buffer overflow.

Vis-à-vis du langage utilisé, le C, nous devions faire attention à la mémoire allouée dynamiquement, avec les primitives telles que ``malloc``, qui peut être source de fuite d'informations sensibles ou source de bug exploitable par un attaquant, il était donc important de bien libérer la mémoire allouée dynamiquement après utilisations, et de ne pas allouer trop de mémoire inutilement.

Pour le traitement des entrées, nous nous protégeons des attaques de type Fuzzing, ou injections SQL avec des techniques de filtrage d'entrée. On utilise une regex pour vérifier le formatage de l'entrée, de cette manière, une entrée que n'aurait pas le format d'un chemin de fichier est rejeté.

Et enfin nous n'utilisons aucun appel récursif, afin de limiter les risques de stack overflow.

Ces règles permettant déjà d'éviter de nombreux risques sur l'implémentation de notre logiciel, il sera plus difficile (voire impossible) pour un attaquant de trouver des failles mémoires pour faire des injections de shellcode, ou alors des attaques plus complexes comme les Return-To-Libc, ROP....

Une fois tout ceci fait, un deuxième travail de rétro ingénierie a été effectué afin de vérifier qu'elle serait le point de vue d'un attaquant qui aurait accès à l'exécutable aussi bien côté client que serveur, et on a remarqué qu'il n'y avait pas, ou tout du moins très peu de faille mémoire simple à exploiter.

## Application de Sécurité

Maintenant que nous avons un cadre de travail "propre", nous avons pu mettre en place différentes mesures de sécurité face aux menaces identifiées plus tôt.

### Gestion des accès

Il est essentiel de mettre en place un système de gestion d'accès pour un logiciel comme Sec Trans, il ne faut pas que n'importe quelles personnes puissent l'utiliser pour éviter que des individus malveillants essayent de nuire à l'intégrité des systèmes du logiciel ou même de l'entreprise, il faut limiter les utilisateurs aux employés de l'entreprise.
Pour ce faire nous avons mis en place un système de Login permettant de s'assurer que seuls les utilisateurs authentifiés peuvent accéder aux fonctionnalités de l'application. Et aussi pour assurer que chaque utilisateur n'est pas accès à d'autre fichiers que ceux qu'il a téléchargés.

Commençons par la partie **LOGIN**. Nous avons choisi le fonctionnement suivant :
1. lors d'une demande d'identification du client vers le serveur, nous utilisons **SHA-256** afin d'obtenir un hash unique qui permettra de l'authentifier de manière unique.
2. Nous créons un dossier par user, ce dossier est reconnu à son nom qui comporte cet hash unique. Il correspond au hash du Username plutot que du mot de passe, la raison est la suivante, supposons que des attaquant aient eu un accès root au serveur, ils pourraient voir les hash et potentiellement retrouver les MDP grâce à des techniques détournées telles que les rainbow tables.



### Transmission sécurisée des données

Pour le moment les fichiers sont simplement transmis dans un canal de transmissions gérer par le framework Macrohard. Le problème est que ce canal n'est pas sécurisé et que potentiellement un attaquant peut écouter sur ce canal et intercepter des données envoyées, et puisqu'elles ne sont pas cryptées il pourra facilement les lire. 

Il est donc vital que les données soient encryptées avant d'être transmises sur le canal de transmission. Pour sécuriser le canal, plusieurs options sont possibles comme un VPN qui garantirait la confidentialité des données échangées, ou l'utilisation de pare-feu pour surveiller le trafic, mais ces protections sont assez complexes à intégrer.

Nous avons donc opté pour l'une des mesures de sécurité les plus importantes de notre système, la cryptographie, car rappelons que Sectrans reste un logiciel de **transfert sécurisé** de fichier entre client et serveur. Donc il est essentiel d'implémenter un protocole d'encryptage des données au moment de l'envoi et de la transmission des fichiers, aussi bien du trajet client-serveur que serveur-client.
Dans notre cas nous utilisons RSA, un algorithme de chiffrement asymétrique très utilisé pour l'échange de données confidentielles, et AES, l'un des algorithmes de chiffrement symétrique le plus sûr. Pour ce dernier nous avons hésité entre AES-256-GCM et AES-256-CBC., en effet GCM offre à la fois l'authentification et le chiffrement, garantissant l'intégrité et la confidentialité des données. Néanmoins GCM est d'une part assez compliqué à implémenter et de plus est plutôt utilisé pour le déchiffrement d'une portion de fichier, or dans notre cas on souhaite chiffrer et déchiffrer des fichiers complets. Donc au final notre choix se portera sur AES-256-CBC.

Comment fonctionne le chiffrement de nos données pour un envoi de fichier ? 
- le serveur et le client génèrent les clés RSA nécessaires pour l'algorithme.
- Ensuite nous échangeons les clés publiques RSA des 2 parties sur le canal de transmission.
- L'échange une fois fini, le serveur va générer une clé de chiffrement pour AES.
- Cette clé AES est chiffrée par la clé RSA du client pour réduire les risques qu'un attaquant qui écouterait sur le serveur découvre la clé.
- Maintenant chiffrer la clé AES est envoyé au client qui pourra la déchiffrer avec sa clé privée.
- Le client en possession de la clé de chiffrement va chiffrer le fichier avec AES.
- Et enfin il peut envoyer le fichier chiffré sur le canal, même si un attaquant récupère ce fichier il ne pourra pas le lire. 
- Et de son coté le serveur peut le déchiffrer au besoin car il possède la clé AES.

Avec ce protocole, on assure que les fichiers sont difficilement exploitables en cas de vol sur le canal par un attaquant, limitant le vol d'information pendant le transfert. Néanmoins il offre une autre possibilité d'attaque due a RSA, les attaques de l'homme du milieu qui a pour but d'intercepter les communications entre deux parties, sans que ni l'une ni l'autre puisse se douter que le canal de communication entre elles a été compromis. Tout le probleme et la faiblesse de ce chiffrement réside dans l'échange de données.


### Confidentialité des données stockées

Une fois nos données transmises au serveur, il est important qu'elle ne soit pas stockée en clair sur ce dernier, un attaquant qui réussirait d'une manière ou d'une autre à avoir accès au serveur et au fichier transmis par un utilisateur n'aurait ainsi aucune difficulté à lire les données stockées dans la base de données.

Comme le point précédant la solution la plus efficace reste la cryptographie, et nous utilisons la fin de notre protocole, c’est-à-dire qu'au moment où le serveur reçoit un fichier il est chiffré, et ainsi pour limiter les risques, il restera stocker chiffré dans le serveur et au moment ont un utilisateur demande ce fichier le serveur enverra avec le protocole RSA definit plutôt la clé de déchiffrement correspondant au client et ensuite le fichier chiffré. 
De cette manière le fichier restera encore complètement chiffré durant toutes la transmission et on limite le vol d'informations sensibles.

Une piste d'amélioration possible pour cet aspect serait d'utiliser un firewall et d'ajouter un outil de surveillance pour détecter toute activité suspecte ou des tentatives d'intrusion. Malheuresement ce n'est pas présent dans notre projet, nous nous limitons à la cryptographie

### Faiblesse face à la rétro-ingenierie 

Comme nous l'avons vu plutôt, nous avons reussi à analyser les fichiers fournis par Macro Hard, ainsi ceux-ci peuvent être sujets à de la rétro-ingénierie par des attaquants. Grâce à cela, des attaquants peuvent analyser le code, et ainsi comprendre le code exécuté pour réaliser les différentes actions, par exemple  le transfert de fichier, et avoir une idée du comportement de notre logiciel et concevoir des attaques.

Pour résoudre ce problème, une des solutions les plus utilisées est l'obfuscation de code. Elle vise à rendre le code source d'un programme difficile à comprendre tout en préservant son fonctionnement, cela peut dissuader les attaquants de comprendre la logique interne du logiciel puisque en plus, dans certains cas elle peut même générer des branchements inutiles dans le code.

Malheureusement nous n'avons pas réussi à implémenter cette fonctionnalité par contre a l'avenir nous pourrions utiliser des outils open source comme : 

https://github.com/obfuscator-llvm/obfuscator

Néanmoins pour ce proteger de cette menaces nous avons pris certaine précautions comme ne pas coder en clair des mot de passe des utilisateur.


### Faiblesse au DDOS

Les attaques par deni de service distribué, DDOS, font partie des menaces possible sur ce genre de logiciel de transfert. En effet un attaquant peut utiliser ce genre d'attaque pour entraîner une surcharge des serveurs, provoquant des temps d'indisponibilité et des retards dans le transfert de fichiers, compromettant ainsi la disponibilité du service, ou encore les attaques DDoS peuvent servir de diversion, masquant d'autres activités malveillantes, et la saturation des ressources peut conduire à des coûts opérationnels significatifs pour maintenir la stabilité du service. Et dans une autre mesure la dégradation des performances peut nuire a la réputations du logiciel.

Pour ce proteger de genre de menaces les solutions les plus efficaces consiste à utiliser des pare-feu et des systèmes de détection des intrusions pour filtrer le trafic malveillant. On peut aussi mettre en place de l'ingénierie sociale avec le maintien d'une politique de sécurité solide, la sensibilisation des utilisateurs aux menaces potentielles.

Une autre solutions plus simpliste serait de mettre en place un nombre d'action effectué par unité de temps, par exemple 2 action par minutes, et une durée de session ainsi, meme si un utilisateur malveillant reussi a ce connecter il ne pourrait pas réaliser autant d'action qu'il le souhaite et ainsi il ne nuirait pas a l'iintégrité de notre système

Malheuresement nous n'avons pas implémenter de protection allons dans ce sens.


## Analyse de Sécurité

Une fois toutes les mesures mises en place, nous avons procédé à une analyse de sécurité de notre logiciel. Nous utilisons deux techniques vus en cours, l'analyse dynamique avec du **fuzzing** et l'analyse statique avec la **retro-ingenierie**, nous avons déjà utilisé cette dernière lors de l'implémentation des grandes fonctionnalités de notre logiciel.

### Analyse statique

Avec l'utilisation d'IDA sur les executables client et serveur, on peut avoir la vision d'un attaquant qui aurait récuperé les binaires de notre logiciel. Nous faisons une analyse globale qui engloble les 2 exécutables, puisque nous n'avons pas retrouvé de faille flagrante sur un exécutable précis.

Premierement on remarque que sans obfuscation du code, des éléments sont facilement reconnaissable grace aux nom des différentes fonction, comme par exemple : 

![image](https://hackmd.io/_uploads/HJapDP_d6.png)

Ainsi un attaquant peut arriver a comprendre qu'un algorithme de chiffrement RSA et AES sont utiliser pour protéger ce logiciel. Cependant il doit encore réflechir et comprendre comment est implémenter notre chiffrement et a quoi ils nous sert.

Autre chose que l'on peut voir a travers l'outils IDA et la table des Imports : 

![image](https://hackmd.io/_uploads/BJCFQdO_p.png)

Cette table permet de localiser tout les imports effectué dans notre logiciel ici on remarquera que l'on retouve les imports standard de la bibliotheques C et aussi ceux de OpenSSL, ainsi un attaquant pourait utiliser cette information afin d'exploiter une faile dans cess bibliotheques. Heuresement les quelque bibliotheques que nous utilisons non pas de faille signalés, mais il sera important de les mettre a jour régulierement a l'avenir.

Pour ce qui est des chaine de caractere reconnaissable dans la décompilation, on ne retrouve que des informations peut importante telles que : 
![image](https://hackmd.io/_uploads/rk0-oOu_T.png)
![image](https://hackmd.io/_uploads/B1G4juu_T.png)
Donc des informations non critique

Et pour ce qui est des différentes fonction de cryptage que nous implémentons, on arrive a les retrouver a travers une analyse statique, cependant on ne peut en tirer peut de chose uniquement le comportement, en effet c'est portions de code sont sécurisé et independante du systeme, elle ne prennent pas en compte les entrées utilisateur.


Les lecons que nous pouvons retenir de cette analyse statique sont les suivantes : 

- Il faut obfusquer le code pour le rendre moins compréhensible.
- Aucune informations sensible n'est présente en clair dans le code
- Les bibliotheques utiliser visible par l'attanquant sont sécurisé
- Il faut retirer certain affichage présent pour enlever des piste qui aiderai a comprendre le code
- Et il n'y a peu, voir pas de faille facilement exploitable visible par une analyse statique

### Analyse dynamique

Pour l'annalyse dynamique nous avons surtout tester des parties précise de notre logiciel grace au fuzzing, il est important de noter que pour essayer cette technique ils nous a été assez compliqué car il faut relancer plusieurs fois le client, puisque un client ne peut lancer qu'une requete a la fois.

Tout d'abord nous avons tester le systeme d'authentification avec un fuzzer qui nous permet de faire du bruteforce provenant de github. 
- https://github.com/ariary/cfuzz

Nous avons utiliser une wordlist, donc malheuresement avec des mot de passe simple, on reussis a se connecter a un utilisateur a partir du moment ou on a son username.  Cela est du au manque de robutesse de nos mot de passe de test.

Ensuite nous avons essayer sur les entrée possible a l'option -up et -down, et cette fois-ci grace a une regex tres specifique nous rejettons toute les autres possibilité. Nous n'avons pas retrouvé d'erreur mal géré ou autres, donc cette partie est sécurisé.

Les lecons que nous pouvons retenir de cette analyse dynamique sont les suivantes : 

- L'utilisation de Regex permet de filtrer efficacement les entrées.
- Nous laissons peut de place a l'injection volontaire d'erreur, et les vérifications ont l'air suffisante pour proteger la plupart des cas d'erreur.
- Neanmoins cette analyse est sans doute trop légere peut etre qu'avec des outiles de fuzzing plus puissant nous aurions pu découvrir d'autre faille


## Conclusion et piste d'amélioration

Donc a travers cette analyse de sécurité on a pu voir que du point de vue de l'attaquant nous obtenons certes des informations telles que des chaines de caractère en clair contenant des nombres, mais ces dernieres ne sont pas forcement utile, il ne pourra pas en tirer grand choses, et de plus notre approche modulaire rend la comprehension du code plus difficile a comprendre meme apres décompilation du binaire, néanmoins un attaquant arrivera a découvrir a quoi servent certaine partie du code comme par exemple la partie de génération des clés RSA. 

Par contre cette analyse dynamique a prouvé que notre filtrage des entrées est efficace, limitant le risque d'atteinte au systeme. Même si, parfois, elle a réussi a braver le systeme d'authentification, mais la cause est differentes elle releve plus de l'ingénierie sociale, nous avions mis des mot de passe trop simpliste. Donc il serait interessant de faire un rappel pour que les utilisateurs utilisent un mot de passe robuste.

En conclusion pour son besoin principal, la transmission de fichier sécurisé le logiciel est sécurisé nottamment grace a des protocoles cryptographiques fort. 

Cependant on peut noter certaine voie d'améliorations pour des menaces DDoS ou de rétro ingénierie, il faudra a l'avenir obfusquer le code, et ajouter une défense plus puissante comme un firewall. En effet dans notre analyse nous n'avons pas vérifier des failles réseaux, avec des outils comme wireshark, il serait aussi interessant d'utiliser un outil de surveillance d'activité sur réseau.


## random  a mettre dans le read me 

Pour utiliser ce projet il vous faudra les librairie libssl-dev et openssl obtenable avec les commande suivantes: 

- sudo apt-get install libssl-dev
- sudo apt-get install openssl

Ensuite pour lancer le projet : 

- make 
- ...