Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Best practices : autoriser la création de fichiers dans un répertoire etc.

15 réponses
Avatar
Francois Lafont
Bonjour à tous,

J'ai un question de sécurité en quelques sorte et j'aimerais
avoir votre avis. Avant, je pense que c'est mieux que je donne
le contexte même si ça va un peu allonger le message (désolé).
C'est un contexte de supervision mais la question elle, n'a pas
de rapport avec la supervision.

Nous avons plusieurs serveurs sur lesquels tournent des tâches
cron. On a une boîte mail dédiées qui reçoit la sortie des crons.
Au final, ça fait un nombre assez important de mails qui arrivent
chaque jour dans cette boîte et du coup plus personnes n'y prête
attention. Sans compter les crons écrits il y a x années qui, en
cas de soucis envoient un mail à telle ou telle personne qui ne
travaille même plus chez nous. Bref, c'est un peu le zouk et je
voudrais tenter te centraliser tout ça via notre logiciel de
supervision.

Ce que je voudrais mettre en place, c'est une sorte de wrapper
pour cron, appelons-le wcron, qui permettrait de stocker quelque
part le exit code du cron afin que le logiciel de supervision
puisse régulièrement aller checker que tous les exit code sont
bien à 0.

Plus précisément, je suppose que sur tous les serveurs, il
existe un répertoire /usr/local/crons/ (ça, ça va). Un appel
d'un cron, au lieu d'être ceci :

/usr/local/bin/cron-truc.sh -o -v arg1 arg2

deviendrait cela :

/usr/bin/wcron --label "cron-truc" -- /usr/local/bin/un-cron.sh -o -v arg1 arg2

Voilà ce que ferait la commande wcron ci-dessus :

- si, dans /usr/local/crons/, le fichier cron-truc (nom issu de
l'option --label) n'existe pas, celui-ci est créé.

- ensuite wcron exécute tout simplement le cron « truc » ie
lance la commande « /usr/bin/un-cron -o -v arg1 arg2 » en
prenant soin de récupérer le exit code cette commande.

- enfin wcron écrit le exit code récupéré précédemment dans le
fichier /usr/local/crons/cron-truc.

Et c'est tout. Ensuite, côté supervision, j'aurais un check
qui scruterait le répertoire /usr/local/crons/ et lancerait
une alerte si un fichier contiendrait autre chose que 0 (pas
de souci de ce côté là non plus).

Mon problème se trouve au niveau de la création du fichier
/usr/local/crons/cron-truc. En effet, je pensais définir les
droits au niveau du répertoire /usr/local/crons/ comme ceci :

drwxr-xr-x root:root

Du coup, si le wcron est lancé en tant que root, pas de souci,
le fichier /usr/local/crons/cron-truc pourra être créé sans
problème. Mais si le wcron est lancé par un compte autre que
root (ce qui arrive souvent), alors là j'ai un problème car le
compte n'aura tout simplement pas le droit de créer le fichier
dans lequel le exit code sera stocké.

Tout mon problème est là, comment faire ? Et je dirais même,
comment faire de manière correcte au niveau sécurité. Peut-être
que c'est une mauvaise idée et peut-être que ma manière de penser
le problème est mauvaise au départ ? (C'est pourquoi j'ai
préféré indiquer tout le contexte.)

Au tout début, j'ai pensé à faire mumuse avec le bit setuid etc.
mais on voit bien sur le web que ce n'est pas trop recommandé
au niveau sécurité. Du coup, pour l'instant, je pense passer
par sudo. Par exemple je crée une commande
/usr/bin/wcron_touch_file qui ferait ceci (en gros, je passe
toutes les étapes de vérifications) :

---------------------------------------------
#!/bin/sh

label="$1"
owner="$2"

touch "/usr/local/crons/$1"
chown "$owner:" "/usr/local/crons/$1"
---------------------------------------------

Et avec sudo, je m'arrangerais pour que /usr/bin/wcron_touch_file
puisse être exécuté par « n'importe qui » en tant que root et
sans mot de passe.

Est-ce ça se tient ou bien est-ce complètement foireux ?
Évidemment, par exemple, ça signifie que potentiellement
n'importe quel compte peu créer autant de fichiers qu'il
veut dans /usr/local/crons/ jusqu'à par exemple remplir
la table des inodes etc. Mais d'un autre côté il me semble
qu'on peut dire exacctement la même chose de /tmp/ et qu'a
priori personne ne s'en émeut, non ?

Sinon, une autre politique consiste à dire que la création
du fichier dans /usr/local/crons/ doit être faite manuellement
une première fois par celui qui met en place le cron. Mais
ça fait une tâche supplémentaire à faire et j'aimais bien
l'idée d'avoir qu'à rajouter le wcron « par dessus » le cron
(avec quand même l'obligation pour celui qui met en place
le cron de bien vérifier que "tout se passe bien" ssi le
exit code est 0).

Bref, je suis encore un peu dans le flou. Il est évident
que je ne souhaite pas mettre en place le moindre trou
de sécurité potentiel etc. C'est pourquoi je me tourne
vers vous. ;)

Merci d'avance pour vos lumières.

--
François Lafont

5 réponses

1 2
Avatar
Francois Lafont
Bonsoir,

Le 12/05/2014 10:29, Kevin Denis a écrit :

Tu peux peut-être mettre les logs de cron dans un fichier dédié?
comme /var/log/cron? Ou /usr/local/cron/logs

Sous debian, le démon rsyslog permet de filtrer à peu près comme on
veut les messages qui lui sont envoyés.



Oui effectivement, c'est une possibilité. Après, j'étais vraiment
parti dans l'idée de faire juste wrapper qui fait tout le travail
sans qu'on ait quoi que ce soit à changer au niveau conf. En fait,
j'ai un paquet « perso » qui installe sur les serveurs toute
sorte de scripts qui me servent pour la supervision et je pensais
simplement y ajouter mon wrapper « wcron » afin de permettre
la « centralisation » des crons comme indiqué dans mon premier
message. Je n'avais donc pas l'intention de modifier la conf des
serveurs à la base. Mais je garde ta proposition sous le coude.

Ceci étant dit, j'ai peut-être une idée qui me permettrait de faire
comme je voulais initialement, mais je ne suis pas sûr que ça soit
vraiment sûr à 100%. En effet, je me suis dit au final que je pourrais
définir sur le répertoire /usr/local/crons/ les droits suivants :

drwxrwsr-t root:staff # notez les bits s et t.

Puis définir dans un fichier sudoers ceci :

ALL ALL=(:staff) NOPASSWD: /usr/bin/touch

puis au niveau du wrapper cron faire un truc comme ça :

if [ ! -e /usr/local/crons/<le-fichier> ]
then
# Création du fichier avec sudo afin que ça
# marche même si on n'est pas root.
sudo -g staff touch /usr/local/crons/<le-fichier>
fi

# Puis on lance le cron donné en argument au wrapper.
# Puis on récupère son exit code et on le place dans le
# fichier créé ci-dessus.

Voilà mon idée dans les grandes lignes. Sachant que le fichier
sudoers, je ne mettrais pas /usr/bin/touch directement mais un
script qui reviendrait à faire un touch au final mais avec des
vérifications sur l'argument reçu, sur le fait que le fichier
cible n'existe pas déjà et pourquoi pas que le répertoire ne
contient pas déjà plus de 100 fichiers (ça serait étonnant qu'il
y ait plus de 100 crons sur un même serveur).

Qu'en pensez vous ? Est-ce que c'est correct au niveau
sécurité ?

--
François Lafont
Avatar
Lucas Levrel
Le 15 mai 2014, Francois Lafont a écrit :

Voilà mon idée dans les grandes lignes. Sachant que le fichier
sudoers, je ne mettrais pas /usr/bin/touch directement mais un
script

Qu'en pensez vous ? Est-ce que c'est correct au niveau
sécurité ?



Je n'en sais pas plus que ce que dit le man sudo :
Running shell scripts via sudo can expose the same kernel bugs that make
setuid shell scripts unsafe on some operating systems (if your OS has a
/dev/fd/ directory, setuid shell scripts are generally safe).


--
LL
Eν οιδα οτι ουδεν οιδα (Σωκρατης)
Avatar
Francois Lafont
Bonjour,

Le 15/05/2014 09:46, Lucas Levrel a écrit :

Qu'en pensez vous ? Est-ce que c'est correct au niveau
sécurité ?



Je n'en sais pas plus que ce que dit le man sudo :
Running shell scripts via sudo can expose the same kernel bugs that make
setuid shell scripts unsafe on some operating systems (if your OS has a
/dev/fd/ directory, setuid shell scripts are generally safe).



Ben globalement, je ne comprends pas trop ce que cela veut dire
tout ça. Que ça puisse causer des trous de sécurité, ok mais là
ça parle de « kernel bugs ». Je ne pige pas vraiment. Pareil,
avec cette histoire de /dev/fd/ (présent sur Debian Wheezy au
passage), je ne connais pas l'utilité de ce répertoire. Je vais
essayer de me renseigner.

--
François
Avatar
Nicolas George
Francois Lafont , dans le message
<5374777d$0$2043$, a écrit :
Ben globalement, je ne comprends pas trop ce que cela veut dire
tout ça. Que ça puisse causer des trous de sécurité, ok mais là
ça parle de « kernel bugs ». Je ne pige pas vraiment. Pareil,



Rien, c'est du n'importe quoi. S'il y a des bugs dans le noyau, rien n'est
sûr, point final.

avec cette histoire de /dev/fd/ (présent sur Debian Wheezy au
passage), je ne connais pas l'utilité de ce répertoire. Je vais
essayer de me renseigner.



Si le noyau exécute un script SUID de manière naïve, il commence par
exécuter l'interpréteur avec des droits élevés puis l'interpréteur ouvre et
lit le script. Il se passe donc une fraction de seconde entre les deux
étapes. Un attaquant peut invoquer le script via un lien symbolique et
profiter de cette fraction de seconde pour remplacer le lien :
l'interpréteur est déjà lancé avec les droits élevés mais le script n'est
pas le bon.

Certains noyaux modernes évitent ce problème en ouvrant eux-mêmes le script,
et en donnant à l'interpréteur un nom symbolique pour le fichier déjà
ouvert, /dev/fd/X.
Avatar
Francois Lafont
Bonsoir,

Le 15/05/2014 11:20, Nicolas George a écrit :
Francois Lafont , dans le message
<5374777d$0$2043$, a écrit :
Ben globalement, je ne comprends pas trop ce que cela veut dire
tout ça. Que ça puisse causer des trous de sécurité, ok mais là
ça parle de « kernel bugs ». Je ne pige pas vraiment. Pareil,



Rien, c'est du n'importe quoi. S'il y a des bugs dans le noyau, rien n'est
sûr, point final.



Ah ok.

avec cette histoire de /dev/fd/ (présent sur Debian Wheezy au
passage), je ne connais pas l'utilité de ce répertoire. Je vais
essayer de me renseigner.



Si le noyau exécute un script SUID de manière naïve, il commence par
exécuter l'interpréteur avec des droits élevés puis l'interpréteur ouvre et
lit le script. Il se passe donc une fraction de seconde entre les deux
étapes. Un attaquant peut invoquer le script via un lien symbolique et
profiter de cette fraction de seconde pour remplacer le lien :
l'interpréteur est déjà lancé avec les droits élevés mais le script n'est
pas le bon.

Certains noyaux modernes évitent ce problème en ouvrant eux-mêmes le script,
et en donnant à l'interpréteur un nom symbolique pour le fichier déjà
ouvert, /dev/fd/X.



Merci pour ces explications Nicolas, j'ai appris quelque chose.


--
François Lafont
1 2