[ 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 ]
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).
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 :
le logiciel s'exécute avec le minimum de droits nécessaires :
le paquet installe des binaires setuid or setgid. Lintian
avertira des binaires setuid
,
setgid
ou setuid et
setgid
;
les démons fournis par le paquet s'exécutent avec un utilisateur aux droits restreints (consultez Création d'utilisateurs et de groupes pour les démons logiciels, Section 9.2) ;
les tâches programmées (c'est-à-dire cron
) s'exécutant sur le
système ne le sont pas en tant que superutilisateur, et si
elle le sont, elles n'implémentent pas de tâches complexes.
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
.
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 :
démarre le démon en abandonnant les droits du superutilisateur : si le
logiciel ne fait pas l'appel setuid(2)
ou seteuid(2)
lui-même, l'option --chuid de start-stop-daemon
est
utilisable.
n'arrête le démon que si l'identifiant utilisateur correspond, l'option
--user de start-stop-daemon
permet de faire cela.
ne s'exécute pas si l'utilisateur ou le groupe n'existent pas :
if ! getent passwd | grep -q "^utilisateur_serveur:"; then echo "L'utilisateur du serveur n'existe pas. Abandon" >&2 exit 1 fi if ! getent group | grep -q "^groupe_serveur:" ; then echo "Le groupe du serveur n'existe pas. Abandon" >&2 exit 1 fi
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 +0000jfs@debian.org