Lanceur de scripts suid

Dans le cadre d’un développement Web, je devais faire exécuter par mon fidèle utilisateur www-data des scripts que seul root eût été à même de mener à bien …

Malheureusement (ou plutôt pas … cf. attaque sushi ou su shell), des restrictions ont été ajoutées pour empêcher l’escalade des droits suid pour les scripts.
La solution à mon problème ayant déjà été traitée par Xavier Garreau dans l’article SUID Scripts, et trouvant l’idée remarquable, je l’ai épousée (euh… l’idée, pas Xavier Garreau !).

Il est est ressorti un petit exécutable sush qui permet de lancer un script avec l’identité et les droits de root, à condition que son nom soit consigné dans un fichier de configuration (typiquement /etc/sush) lequel doit avoir des droits d’accès limités au seul utilisateur root, évidemment.

Le code C :

#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

extern char **environ;
extern int errno;

#define CHEMIN_AUTORISATIONS "/etc/sush"

int
main (int argc, char **argv)
{
FILE *fd;
uid_t uid, euid;
int isOK = 0;
char tmpBuff[1024];
struct stat statbuf;

if (argc < 2)
{
fprintf (stderr, "USAGE : sush nom_du_script param_1 param_2 ...\n");
return 1;
}

memset (&tmpBuff, 0, sizeof(tmpBuff));
if (! stat(CHEMIN_AUTORISATIONS, &statbuf) )
{
if (statbuf.st_uid || statbuf.st_gid)
{
fprintf (stderr, "ERREUR : Le fichier de configuration %s doit appartenir à l'utilisateur root (groupe root).\n", CHEMIN_AUTORISATIONS);
return 3;
}
if (statbuf.st_mode & 0x77)
{
fprintf (stderr, "ERREUR : Le fichier de configuration %s ne doit être accessible qu'à l'utilisateur root (groupe root).\n", CHEMIN_AUTORISATIONS);
return 4;
}
}
else
{
fprintf (stderr, "ERREUR : Fichier de configuration (%s) inexistant.\n", CHEMIN_AUTORISATIONS);
return 5;
}

/* escalade des droits d'exécution (sush est suid root) */
uid = getuid ();
euid = geteuid ();
setreuid (euid, euid);

/* Vérfication de l'autorisation du script à lancer */
if (!(fd = fopen (CHEMIN_AUTORISATIONS, "r")))
{
fprintf (stderr, "ERREUR : Impossible d'ouvrir le fichier de configuration des scripts autorisés (%s).\n", CHEMIN_AUTORISATIONS);
return 2;
}

while (!feof (fd))
{
fscanf (fd, "%s", tmpBuff);
if (!strcmp (argv[1], tmpBuff))
{
isOK++;
break;
}
}
fclose (fd);

if (!isOK)
{
fprintf (stderr, "ERREUR : %s n'est pas un script autorisé...\n", argv[1]);
return 3;
}

/* lancement du script */
sprintf (tmpBuff, "%s", argv[1]);
execve (tmpBuff, &argv[1], environ);
printf ("Erreur : %d - %s\n", errno, strerror (errno));
return errno;
}

à compiler ainsi :

sudo gcc -O2 -o /usr/bin/sush sush.c && sudo chmod u+s /usr/bin/sush

pour obtenir un exécutable /usr/bin/sush doté de l’attribut suid root.

Enfin, la création du fichier de configuration idoine, qui permettra à l’administrateur système que vous êtes de limiter l’usage de sush :

sudo touch /etc/sush && sudo chmod 600 /etc/sush

et son peuplement :

sudo echo "/usr/local/scripts/monscript_que_je_veux_que_tout_le_monde_puisse_executer" >> /etc/sush

Et voilà …

posté le 12. décembre 2009 à 9:04 am par info · Permalink
Catégories : Administration système, Shell · Mots-clés: ,

Ajoutez un commentaire