Nombreux sont ceux qui espère trouver la solution ultime pour protéger les différents scripts Bash/Sh qu’ils produisent. Il n’est pas rare, loin de là, de déployer des scripts shell critiques sur des environnements de production et des serveurs en-ligne.
Pourquoi critique? Car le code source de ces scripts est accessible en clair, et qu’ils renferment souvent des informations qui s’avèrent être d’un grand intérêt pour quelqu’un de malintentionné (mots de passe réseau, de bases de données, etc.).
Ces scripts peuvent être aussi divers que variés. A titre d’exemple, de tels scripts sont souvent :
- Des scripts de sauvegardes/backups d’annuaires ou de base de données, exécutés périodiquement (tâches cron)
- Des scripts de nettoyage de caches/fichiers, d’archivage ou encore de compression
- Des systèmes de surveillances/monitoring qui vérifient l’utilisation RAM/CPU/DISK d’un serveur
- Des moyens d’externaliser des backups sur des emplacements réseaux distants
Tous les administrateurs systèmes ont déjà été amenés au moins une fois à exploiter de tels scripts.
Certaines bonnes pratiques permettent toutefois d’accroître la sécurité de ces fichier sensibles sous un environnement Linux :
- Forcer la demande de mot de passe/passephrase à un utilisateur dédié lors de l’exécution du script. Certes cette méthode nécessite une intervention manuelle mais reste une des plus sûres.
- Pour les scripts en tâches panifiées, ceux-ci doivent être autonomes et ne doivent pas nécessiter d’intervention manuelle. Ainsi, ces scripts sont généralement confinés dans des répertoires du système protégés (/root) afin d’être uniquement exécutables/modifiables par un utilisateurs aux permissions suffisantes.
- Les mots de passes contenus dans ces fichiers sont très souvent changés et complexifiés lors d’une mise en production.
- Enfin, il est possible de chiffrer ces scripts afin d’amoindrir les chances d’en visualiser le contenu (et les mots de passes) en clairs.
Une solution existe depuis plusieurs années, permettant de transformer un script « *.sh » en un binaire dont le code source du script initial est entièrement chiffré et embarqué dans ce binaire. L’idée est d’empêcher la visualisation du code source du script en clair et de décourager certains curieux aux actions malveillantes.
La solution se nomme « shc » pour « SHell Compiler ». Ce petit outil OpenSource développé par Francisco Javier Rosales Garcia dont la dernière version en date est la 3.8.9 permet de chiffrer n’importe quel script interprété sous un terminal Linux.
Pour s’en équiper, télécharger la dernière version et compiler l’outil :
wget -q http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.9.tgz tar zxvf shc-3.8.9.tgz cd shc-3.8.9 ln -s shc-3.8.9.c shc.c make
L’aide de SHc renseigne sur son utilisation :
root@server:~/shc/shc-3.8.9# shc -h shc Version 3.8.9, Generic Script Compiler shc Copyright (c) 1994-2012 Francisco Rosales <frosal@fi.upm.es> shc Usage: shc [-e date] [-m addr] [-i iopt] [-x cmnd] [-l lopt] [-rvDTCAh] -f script -e %s Expiration date in dd/mm/yyyy format [none] -m %s Message to display upon expiration ["Please contact your provider"] -f %s File name of the script to compile -i %s Inline option for the shell interpreter i.e: -e -x %s eXec command, as a printf format i.e: exec('%s',@ARGV); -l %s Last shell option i.e: -- -r Relax security. Make a redistributable binary -v Verbose compilation -D Switch ON debug exec calls [OFF] -T Allow binary to be traceable [no] -C Display license and exit -A Display abstract and exit -h Display help and exit Environment variables used: Name Default Usage CC cc C compiler command CFLAGS C compiler flags Please consult the shc(1) man page.
Pour illustrer le fonctionnement de SHc, voici un simple script (totalement inutile) qui contient des informations sensibles. Ce script est voué à un déploiement en production :
#!/bin/bash # This script is very critical ! echo "I'm a super critical and private script !" PASSWORDROOT="SuPeRrOoTpAsSwOrD"'; myService --user=root --password=$PASSWORDROOT > /dev/null 2>&1
SHc permet de chiffrer le code source précédent du script afin de concevoir un binaire autonome qui réalise les tâches équivalentes :
[root@server:~/scripts/shc]$ ./shc -v -r -f myScript.sh shc shll=bash shc [-i]=-c shc [-x]=exec '%s' "$@" shc [-l]= shc opts= shc: cc myScript.sh.x.c -o myScript.sh.x shc: strip myScript.sh.x shc: chmod go-r myScript.sh.x [root@server:~/scripts/shc]$ ll myScript.sh* -rwxr-xr-x 1 root root 191 2013-07-18 17:03 myScript.sh* -rwx--x--x 1 root root 10508 2013-07-18 17:06 myScript.sh.x* -rw-r--r-- 1 root root 10421 2013-07-18 17:06 myScript.sh.x.c
A la suite de l’exécution de SHc, deux fichiers sont produits :
- Le binaire qui embarque la source du script Sh initial, chiffrée et exécutable. L’extension de ce fichier est « *.sh.x »
- Le code source en C, généré à la volée par SHc, correspondant au binaire protégé. Ce code source porte l’extension « *.sh.x.c ».
On notera que le binaire chiffré réalise exactement les mêmes actions que le script initial :
[root@server:~/scripts/shc]$ ./myScript.sh I'm a super critical and private script ! [root@server:~/scripts/shc]$ ./myScript.sh.x I'm a super critical and private script !
La version actuelle de SHc génère un code C « *.sh.x.c » qui varie à chaque exécution. La déclaration des variables et les vecteurs cryptographiques est aléatoire à chaque protection. L’utilisation du « -r » permet d’étendre la compatibilité du binaire chiffré vers d’autres plateformes.
La version binaire chiffré peut être placée sur un serveur de production afin d’augmenter la sécurité de celui-ci. Bien évidemment, il est conseillé de conserver le script original dont la source est accessible.
Le fonctionnement général de shc est le suivant :
- Analyse du script en entrée
- Chiffrement de son code source à l’aide d’une clé RC4 unique
- Génération d’un code source C dont la structure est aléatoire
- Ce code source C contient la version chiffrée du code source du script Bash/Sh initial, ainsi que les vecteurs clés de déchiffrement.
- Ce code source C contient également l’algorithme inverse de déchiffrement
- Ce code source « *.x.c » est compilé pour donner un binaire final.
- A l’exécution de ce binaire, les variables chiffrées qu’il renferme sont déchiffrées à la volée avec la clé qu’il contient également. Puis la source déchiffrée est interprétée directement via « execvp() » pour produire le résultat attendu.
L’outil shc permet également d’intégrer une notion de validité temporelle du script. Au delà d’une certaine date (temps d’utilisation), son exécution est bloquée pour laisser place à un message arbitraire.
Cet outil améliore sensiblement la sécurité des scripts sensibles qui sont déployés sur des serveurs unix de production. Toutefois, il convient de garder à l’esprit que le binaire produit par SHc est « stand-alone ». Ce qui signifie qu’il est totalement indépendant pour son exécution. Il contient par conséquent la source du script Sh initial (chiffrée), ainsi que tout le matériel cryptographique nécessaire au déchiffrement et à sa propre exécution. Il est donc tout à fait possible de régénérer le script sh initial en n’ayant que le binaire protégé.
Pour illustrer ces propos, un article dédié sur le déchiffrement manuel d’un script « *.sh.x » protégé par SHc apparaîtra très prochainement.
Sources & ressources :