[ précédent ] [ Table des matières ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ] [ H ] [ suivant ]


Securing Debian Manual
Chapitre 9 - Meilleures pratiques de sécurité pour les développeurs


Ce chapitre introduit certaines des meilleures pratiques de code sécurisé pour les développeurs écrivant des paquets Debian. Si vous êtes vraiment intéressé par le code sécurisé, vous devriez lire le HOWTO de programmation sécurisée pour Linux et UNIX de David Wheeler et Secure Coding: Principles and Practices de Mark G. Graff et Kenneth R. van Wyk (O'Reilly, 2003).


9.1 Meilleures pratiques de vérification et conception sécurisées

Les développeurs qui empaquettent des logiciels devraient faire de leur mieux pour s'assurer que l'installation du logiciel, ou son utilisation, n'introduit pas de risques en matière de sécurité à la fois au système où il est installé et à ses utilisateurs.

Pour ce faire, ils devraient faire de leur mieux pour examiner le code source du paquet et détecter tous les défauts qui pourraient introduire des bogues de sécurité avant de publier le programme ou de distribuer une nouvelle version. Il est reconnu que le coût de correction de bogues augmente aux différentes étapes de son développement, il est donc plus facile (et moins coûteux) de corriger les bogues lors de la conception qu'une fois le logiciel déployé et en mode maintenance (plusieurs études disent que le coût dans cette dernière phase est soixante fois plus élevé). Bien que plusieurs outils essayent de détecter automatiquement ces défauts, les développeurs devraient faire leur possible pour se tenir au courant des différents types de défauts de sécurité afin de les comprendre et être capable de les remarquer dans le code qu'ils (ou d'autres) ont écrit.

Parmi les bogues de programmation qui conduisent à des bogues de sécurité, les plus typiques sont les dépassements de tampon, les dépassements de chaîne de formatage, les dépassements de tas et les dépassements d'entier (dans les programmes en C ou C++), les conditions de situation de compétition de liens symboliques temporaires (dans les scripts), les traversées de répertoires et les injections de commande (sur les serveurs) et scripts intersites, et les bogues d'injection SQL (dans le cas des applications orientées web). Pour de plus amples renseignements sur les bogues de sécurité, consultez la taxonomie des erreurs de sécurité de logiciels de Fortify.

Certains de ces problèmes pourraient ne pas être faciles à repérer à moins d'être un expert dans le langage de programmation utilisé par le logiciel, mais certains problèmes sont faciles à détecter et à corriger. Par exemple, trouver des conditions de situation de compétitions temporaires à cause d'une mauvaise utilisation de répertoires temporaires peut se faire facilement en exécutant « grep -r "/tmp/" . ». Ces appels peuvent être examinés et les noms de fichiers écrits en dur, utilisant des répertoires temporaires, remplacés par des appels à mktemp ou tempfile dans les scripts d'interpréteur, File::Temp(3perl) dans les scripts Perl ou tmpfile(3) en C ou C++.

Certains outils permettent d'aider à l'examen de sécurité du code, comme rats, flawfinder et pscan. Pour de plus amples renseignements, consultez la liste d'outils utilisés par l'équipe d'audit de sécurité Debian.

Lors de l'empaquetage, les développeurs de logiciel doivent s'assurer de suivre les principes de sécurité habituels, y compris :

Si vous devez faire l'un des deux, assurez-vous que les programmes qui pourraient s'exécuter avec des privilèges plus élevés ont été contrôlés pour les bogues de sécurité. En cas de doute, ou pour obtenir de l'aide, contactez l'équipe d'audit de sécurité Debian. Pour les binaires setuid ou setgid, suivez la section de la charte Debian sur les droits et propriétaires.

Pour de plus amples renseignements, spécifiques à la programmation sécurisée, assurez vous de lire (ou d'indiquer en amont) le HOWTO de programmation sécurisée pour Linux et UNIX et le portail Build Security In.


9.2 Création d'utilisateurs et de groupes pour les démons logiciels

Si le logiciel exécute un démon qui n'a pas besoin des droits du superutilisateur, vous devez lui créer un utilisateur. Deux types d'utilisateurs Debian peuvent être utilisés par les paquets : avec identifiant (UID) statique (attribué par base-passwd ; consultez Les utilisateurs et les groupes du système d'exploitation, Section 12.1.12 pour une liste des utilisateurs statiques dans Debian) et avec identifiant dynamique dans l'intervalle dévolu aux utilisateurs système.

Dans le premier cas, il faut demander un identifiant de groupe ou d'utilisateur à base-passwd. Une fois l'utilisateur disponible, le paquet doit être distribué avec une dépendance sur la version adéquate du paquet base-passwd.

Dans le second cas, il faut créer un utilisateur système en preinst ou en postinst et rendre le paquet dépendant de adduser (>= 3.11).

L'exemple de code suivant crée les utilisateur et groupe utilisés par le démon pour s'exécuter quand le paquet est installé ou mis à niveau :

     [...]
     case "$1" in
       install|upgrade)
     
       # Si le paquet a un fichier « default » permettant à
       # l'administrateur local d'écraser les valeurs par défaut
     
       [ -f "/etc/default/nompaquet" ] && . /etc/default/nompaquet
     
       # Valeurs par défaut correctes :
     
       [ -z "$SERVER_HOME" ] && SERVER_HOME=rép_serveur
       [ -z "$SERVER_USER" ] && SERVER_USER=utilisateur_serveur
       [ -z "$SERVER_NAME" ] && SERVER_NAME="Description du serveur"
       [ -z "$SERVER_GROUP" ] && SERVER_GROUP=groupe_serveur
     
       # Groupes auxquels l'utilisateur sera ajouté ; aucun si non défini.
       ADDGROUP=""
     
       # créer un utilisateur pour éviter d'exécuter le serveur en tant
       # que superutilisateur
       # 1. Créer le groupe s'il n'existe pas
       if ! getent group | grep -q "^$SERVER_GROUP:" ; then
          echo -n "Ajout du groupe $SERVER_GROUP.."
          addgroup --quiet --system $SERVER_GROUP 2>/dev/null ||true
          echo "fait"
       fi
       # 2. Créer un répertoire personnel s'il n'existe pas
       test -d $SERVER_HOME || mkdir $SERVER_HOME
       # 3. Créer un utilisateur s'il n'existe pas
       if ! getent passwd | grep -q "^$SERVER_USER:"; then
         echo -n "Ajout de l'utilisateur système $SERVER_USER.."
         adduser --quiet \
                 --system \
                 --ingroup $SERVER_GROUP \
                 --no-create-home \
                 --disabled-password \
                 $SERVER_USER 2>/dev/null || true
         echo "fait"
       fi
       # 4. Ajuster l'entrée de mot de passe
       usermod -c "$SERVER_NAME" \
               -d $SERVER_HOME   \
               -g $SERVER_GROUP  \
                  $SERVER_USER
       # 5. Ajuster les droits des fichiers et répertoires
       if ! dpkg-statoverride --list $SERVER_HOME >/dev/null
       then
           chown -R $SERVER_USER:adm $SERVER_HOME
           chmod u=rwx,g=rxs,o= $SERVER_HOME
       fi
       # 6. Ajouter l'utilisateur au groupe ADDGROUP
       if test -n $ADDGROUP
       then
           if ! groups $SERVER_USER | cut -d: -f2 | \
              grep -qw $ADDGROUP; then
                adduser $SERVER_USER $ADDGROUP
           fi
       fi
       ;;
       configure)
     
     [...]

Assurez-vous que le fichier de script init.d :

Si le paquet crée l'utilisateur système, il peut le retirer lors de la purge en postrm. Cela a cependant quelques inconvénients. Par exemple les fichiers créés par cet utilisateur seront orphelins et pourraient être repris par un nouvel utilisateur système plus tard si le même identifiant utilisateur lui est attribué[64]. Par conséquent, retirer les utilisateurs système lors de la purge n'est pas encore obligatoire et dépend des besoins du paquet. En cas de doute, cette action pourrait être faite en demandant à l'administrateur sa préfèrence lors du retrait du paquet (c'est-à-dire avec debconf).

Le code exemple suivant [65] retire l'utilisateur et les groupes créés auparavant seulement, et seulement si, l'identifiant utilisateur est dans l'intervalle des identifiants utilisateur dynamiques attribués pour le système et que l'identifiant de groupe appartient à un groupe système :

     case "$1" in
      purge)
     [...]
        # trouver les premier et dernier numéros de SYSTEM_UID
        for LINE in `grep SYSTEM_UID /etc/adduser.conf | grep -v "^#"`; do
           case $LINE in
              FIRST_SYSTEM_UID*)
                FIST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
                ;;
              LAST_SYSTEM_UID*)
                LAST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
                ;;
              *)
                ;;
              esac
        done
        # supprimer le compte système si nécessaire
        CREATEDUSER="utilisateur_serveur"
        if [ -n "$FIST_SYSTEM_UID" ] && [ -n "$LAST_SYSTEM_UID" ]; then
         if USERID=`getent passwd $CREATEDUSER | cut -f 3 -d ':'`; then
           if [ -n "$USERID" ]; then
             if [ "$FIST_SYSTEM_UID" -le "$USERID" ] && \
                [ "$USERID" -le "$LAST_SYSTEM_UID" ]; then
                   echo -n "Suppression de l'utilisateur système $CREATEDUSER"
                   deluser --quiet $CREATEDUSER || true
                   echo "fait"
             fi
           fi
         fi
       fi
       # supprimer le groupe système si nécessaire
       CREATEDGROUP=groupe_serveur
       FIRST_USER_GID=`grep ^USERS_GID /etc/adduser.conf | cut -f2 -d '='`
       if [ -n "$FIST_USER_GID" ] then
         if GROUPGID=`getent group $CREATEDGROUP | cut -f 3 -d ':'`; then
           if [ -n "$GROUPGID" ]; then
             if [ "$FIST_USER_GID" -gt "$GROUPGID" ]; then
               echo -n "Suppression du groupe $CREATEDGROUP"
               delgroup --only-if-empty $CREATEDGROUP || true
               echo "fait"
             fi
           fi
         fi
       fi
     [...]

L'exécution de programmes avec un utilisateur ayant des droits restreints assure qu'aucun problème de sécurité ne pourra endommager tout le système. Cela suit aussi le principe du minimum de droits. Songez aussi à limiter les droits dans les programmes avec d'autres mécanismes que l'exécution en tant que non superutilisateur[66]. Pour de plus amples renseignements, consultez le chapitre Minimiser les droits du livre HOWTO de programmation sécurisée pour Linux et UNIX.


[ précédent ] [ Table des matières ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ] [ H ] [ suivant ]


Securing Debian Manual

Version: 3.13, Sun, 08 Apr 2012 02:48:09 +0000

Javier Fernández-Sanguino Peña jfs@debian.org
Auteurs, Section 1.1