shc : Protéger les sources de scripts shell

Le shell permet de réaliser rapidement des scripts puissant, mais l’aspect « script » sous entend un accès aux sources du programme ce qui peut devenir problématique pour la diffusion ou la mise en production (mots de passe en clair dans les sources, nom de serveurs, etc).

shc (generic SHell script Compiler) tente de régler ce type de problème en générant un binaire destiné à dissimuler le code source du script (sh, bash, ksh, csh).

Installation

« shc » Est rarement packagé sur les distributions, mais sa compilation et son installation sont triviales.

Télécharger les sources d’shc depuis le site de l’auteur Francisco ROSALES (http://www.datsi.fi.upm.es/~frosal/) et les décompresser :

fhh@mafalda ~ $ mkdir src
fhh@mafalda ~ $ cd !$
cd src
fhh@mafalda ~/src $ wget -q http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.9.tgz
fhh@mafalda ~/src $ tar xf shc-3.8.9.tgz
fhh@mafalda ~/src $ ls
shc-3.8.9  shc-3.8.9.tgz
fhh@mafalda ~/src $ cd shc-3.8.9
fhh@mafalda ~/src/shc-3.8.9 $

Note : Dans les dernières sources, le Makefile est écrit pour compiler « shc.c » mais le fichier source est nommé « shc-X.Y.Z.c ». Créer un lien symbolique ou renommer le fichier source règlera cet incident.

fhh@mafalda ~/src/shc-3.8.9 $ ls
CHANGES  makefile  pru.sh  shc-3.8.9.c  shc.README  test.csh
Copying  match     shc.1   shc.html     test.bash   test.ksh
fhh@mafalda ~/src/shc-3.8.9 $ ln -s shc-3.8.9.c shc.c

Un simple « make » dans le répertoire des sources assure la compilation de l’utilitaire (dépendance « make » et « cc ») :

fhh@mafalda ~/src/shc-3.8.9 $ make
cc -Wall  shc.c -o shc
***	?Do you want to probe shc with a test script?
***	Please try...	make test

L’utilitaire « shc » est créé dans le répertoire courant et peut-être déplacé où vous le souhaitez sur votre système :

fhh@mafalda ~/src/shc-3.8.9 $ ls
CHANGES  makefile  match.x    pru.sh  shc.1        shc.c     shc.README  test.csh
Copying  match     match.x.c  shc     shc-3.8.9.c  shc.html  test.bash   test.ksh
fhh@mafalda ~/src/shc-3.8.9 $ mkdir ~/bin
fhh@mafalda ~/src/shc-3.8.9 $ mv shc ~/bin/
fhh@mafalda ~/src/shc-3.8.9 $ export PATH="~/bin/:$PATH"
fhh@mafalda ~/src/shc-3.8.9 $ cd
fhh@mafalda ~ $ shc
shc parse(-f): No source file specified
 
shc Usage: shc [-e date] [-m addr] [-i iopt] [-x cmnd] [-l lopt] [-rvDTCAh] -f script

Utilisation d’shc

Sans surprise, « -h » fourni une liste des options disponibles.

Masquer les sources/compiler un script

Le script à compiler est passé en argument à « shc » via l’option « -f ».

fhh@mafalda ~/tmp/test $ shc -vf exemple.sh 
shc shll=bash
shc [-i]=-c
shc [-x]=exec '%s' "$@"
shc [-l]=
shc opts=
shc: cc  exemple.sh.x.c -o exemple.sh.x
shc: strip exemple.sh.x
shc: chmod go-r exemple.sh.x

L’option « -v » détaille les actions de shc sur le script.

Le binaire généré porte le nom complet du script original auquel est ajouté l’extension « .x ». Le binaire est rendu exécutable directement par l’utilitaire après la compilation. :

23:07:15 fhh@mafalda ~/tmp/test $ ls -l
total 28
-rwxr--r-- 1 fhh users    34 Aug 19 23:03 exemple.sh
-rwx--x--x 1 fhh users 11688 Aug 19 23:07 exemple.sh.x
-rw-r--r-- 1 fhh users  9229 Aug 19 23:07 exemple.sh.x.c

le fichier « .x.c » est le code source généré par « shc ».

Le binaire est exécuté comme n’importe quel binaire du système :

fhh@mafalda ~/tmp/test $ ./exemple.sh.x 
Hello world !

Définir une date d’expiration au script

Il est possible de définir une date d’expiration au script par l’option « -e DD/MM/YYYY ». L’argument « -m string » permet d’ajouter un message (ici « string »), affiché à chaque exécution après la date d’expiration.

Exemple de définition d’une date d’expiration :

fhh@mafalda ~/tmp/test $ shc -e 31/12/2012 -m "Contactez fhh@admin-linux.fr" -f exemple.sh
fhh@mafalda ~/tmp/test $ ./exemple.sh.x
Hello world !

Exemple de script expiré (hier) :

fhh@mafalda ~/tmp/test $ shc -e $(date --date="yesterday" +%d/%m/%Y) -m "Contactez fhh@admin-linux.fr" -f exemple.sh
fhh@mafalda ~/tmp/test $ ./exemple.sh.x 
./exemple.sh.x: has expired!
Contactez fhh@admin-linux.fr

Exemples d’utilisation

Le masquage de sources de scripts prend tous son sens dans certains cas d’utilisation courant tel que :

  • les scripts de connexions ftp où les identifiants utilisateurs (login, mot de passe et serveur destination) doivent être stockés en clair dans le corps du programme ;
  • les scripts de sauvegardes de bases de données pour les mêmes raisons que les scripts de connexion ftp ;

Références

shc : http://www.datsi.fi.upm.es/~frosal/
man shc : http://www.datsi.fi.upm.es/~frosal/sources/shc.html
Article sur shc : Paranoid Penguin – Limitations of shc, a Shell Encryption Utility

19 réflexions au sujet de « shc : Protéger les sources de scripts shell »

  1. Pourtant en faisant en ligne de commande, j’obtiens bien « 2 heures après ».

    J’ai contacté l’auteur pour un éventuel ajout sans trop y croire ^^

    Merci pour votre aide 😉

    Bonne journée.

  2. Bonjour,

    comment faire pour:
    ./shc -v -r -T -e $(date –date=’2 hour ago’) -m « Contact Admin » -f abcd.sh

    Il me retourne:
    shc parse(-e samedi): Not a valid value

    Wheezy 64 bits (UTC+0200)

    Cordialement,

    1. Le format de la date n’est pas bon (DD/MM/YYYY attendu). Un truc du genre :


      ./shc -v -r -T -e "$(date –date=’2 hour ago’ +%d/%m/%Y)" -m “Contact Admin” -f abcd.sh

      devrait donner de meilleurs résultats, mais je n’ai pas essayé en précisant l’heure …

      1. non cela ne marche pas, j’avais déjà testé :
        date: opérande supplémentaire « hour »
        Saisissez « date –help » pour plus d’informations.
        shc parse(-e ): Not a valid value
        shc parse(-f): No source file specified

        Merci quand même.

        1. Là, le problème ne vient pas de « shc » mais de « date ». Il y a 2 tirets sur la version longue de l’option « date » de date. Attention aux copiés/collés 😉 Avec l’option courte, ça donne :
          ./shc -v -r -T -e $(date -d "2 hour ago" +%d/%m/%Y) -m 'Contact Admin' -f my.sh
          Par contre, je confirme que l’heure ne peut être précisée (format de date : DD/MM/YYYY).

          1. C’est le blog qui retire le tiret mais bon j’aurais du le voir en copiant 🙁

            C’est génial, la commande passe à merveille !

            Merci !!!

            1. Ah non pardon, après test, l’ajout de deux heures ne passe pas…

              ./shc -v -r -T -e $(date -d « 2 hour ago » +%d/%m/%Y) -m ‘Contact Admin’ -f abcd.sh

              La compilation passe et lors de son xécution (directement après l’avoir compilé) :

              ./abcd.sh.x: has expired!
              Contact Admin

              donc il semblerait qu’il n’accepte pas l’argument…

              1. Comme je le disais à la fin de mon précédent commentaire, l’heure d’expiration ne peut être précisée.
                L’heure est forcément fixée à 00:00 (minuit).

                Au passage, même si vous aviez pu préciser l’heure, le résultat aurait été le même : « 2 hour ago » = « il y a 2 heures », votre script serait donc expiré depuis 2 heures.

  3. si vous avez le message suivant quand vous compiller vos programme avec shc

    ./nomdufichier.x: Operation not permitted
    Processus arrêté

    essayer avec l’option suivante

    shc -v -r -T -f nomdufichier

  4. Bonjour,

    Moi aussi shc -f bloque quand le script est trop complexe (du moins, je le suppose), la compilation se passe sans probleme, mais quand j’essai de lancer le binaire :

    ./script_sh.x: ��6hh;ݓ@� »rFY�Qn

    Arg..

    1. Après discussion avec OwNeD67, une partie du problème était dûe à l’encodage des retours chariots (CRLF -« \r\n »- posait problème et non LF-« \n »-).
      Son script corrigé à fonctionné chez moi et chez lui si je ne me trompe. Malheureusement, le temps m’a manqué pour finir le débogage 🙁 (problèmes de seg fault).

      Que retourne la commande « file » sur les sources de votre script ?

      1. Bonsoir,

        non non désolé mais cela ne fonctionne pas du tout, une fois exécuté sur autre machine ou un autre user, ça plante…

        file gmsts-gs.sh
        gmsts-gs.sh: POSIX shell script text executable

        file gmsts-gs (compilé)
        gmsts-gs: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

        ./gmsts-gs
        ./gmsts-gs: Operation not permitted
        Processus arrêté

  5. Cela rend le bash inexploitable lors de son exécution ./mon_script.sh ou avec sh mon_script.sh…

    J’avais pas vu la nouvelle version… Un script de 2500 lignes ^^

    Je vous tiendrais au courant car moi même, je n’avais pas eu ce problème, ce sont des utilisateurs qui m’ont repporté ce bug à l’époque de la version 3.7 de SHC.

    1. Voici les erreurs rencontrés avec l’ancienne version :

      ./gmsts-gs.sh
      ./gmsts-gs.sh:Ú©±ÔUí^h
      Ö*Iz_çè6ÂH¤ïó:¤V}]ºJ¡²F»Éƾpd
      ß6bên!

      Et avec sh gmsts-gs.sh

      serveur@ks399972:~/srcds$ sh gmsts-gs.sh
      gmsts-gs.sh: gmsts-gs.sh : fichier binaire impossible à lancer
      serveur@ks399972:~/srcds$

        1. Merci pour les retours, d’autres lecteurs rencontrent peut-être, ou ont résolu (?), les mêmes problèmes ?

          N’hésitez pas à nous faire part de vos expériences !!!

    1. Quel genre de problème ? ralentissements violents ? Quelle taille les scripts ?

      Pour les tests, j’ai fait des essais sur des scripts très courts (« hello world ») et sur d’autres plus longs (~500 lignes avec fichiers de config séparés) sans problèmes particuliers…

      Les problèmes sont survenus sur des scripts Bash ?

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *