Il peut arriver d’avoir besoin d’automatiser des actions sur un serveur linux via une page web, typiquement en PHP. Ne trouvant que peu de documentation sur ce principe, je vous propose une solution qui devrait fonctionner sur la majorité des serveurs (testée sous Debian et Ubuntu pour mon cas).
Nous allons dans cet exemple redémarrer le service DNS (Bind9) grâce à un formulaire html exécutant cette fameuse commande via un bout de code PHP.
Identifier l’utilisateur Apache
Les scripts PHP interprétés par Apache sont exécutés par un utilisateur système. Généralement il s’agit de « www-data« , mais il peut varier selon les distributions et configurations. Pour récupérer ce nom d’utilisateur vous avez trois solutions :
- Ouvrir le fichier de configuration Apache « apache2.conf« , généralement situé dans /etc/apache2/apache2.conf (si vous le ne trouvez pas faites un « locate apache2.conf » il devrait vous indiquer son emplacement). Dans le premier quart tu fichier vous devriez trouver l’information voulue :

- Ouvrir le fichier des utilisateurs systèmes /etc/group/ et cherchez celui qui semble correspondre
- Lancer le service Apache (en root : /etc/init.d/apache2 start) puis faites un : ps aux | grep apache2. Vous devriez avoir le nom d’utilisateur sous lequel le service fonctionne.
Le fichier sudoers
Nous allons utiliser la commande sudo qui va permettre à l’utilisateur Apache (www-data pour mon cas) de lancer une commande qui n’est habituellement exécutable qu’en root. Je vous conseilel de lire cette documentation si vous n’avez jamais entendu parlé de sudo.
Editez le fichier /etc/sudoers via la commande visudo (il est fortement déconseiller de l’éditer directement), puis trouvez cette ligne :
root ALL=(ALL) ALL
En dessous de cette ligne ajoutez :
www-data ALL=(ALL) NOPASSWD:/etc/init.d/bind9 restart
Pensez à remplacer www-data par votre utilisateur s’il diffère (cf. première étape).
Grâce à cette ligne nous autorisons l’utilisateur d’Apache a exécuter cette commande, et uniquement celle-ci ! C’est un point important sur la sécurité de votre système. Dans le cas contraire sachez que la sécurité de votre système serait totalement compromise :
www-data ALL=(ALL) NOPASSWD:ALL
Dans ce cas précis, vous autorisez toutes les commandes du systèmes à être exécutées par votre utilisateur Apache, bien évidemment c’est fortement déconseillé !
Le cas d’un script shell
Si vous préférez exécuter un script (.sh) qui s’occupera lui même de réaliser cette opération, il vous faut placer dans votre fichier /etc/sudoers (toujours via la commande visudo) le code suivant (ignorer dans ce cas la première manipulation) :
www-data ALL=(ALL) NOPASSWD: DNSRELOAD
# Cmnd alias specification
Cmnd_Alias DNSRELOAD = /chemin/vers/votre/script.sh
D’une façon générale :
Cmnd_Alias NomDeVotreAlias = NomDeVotreAlias ListeDeCommandesSepareesParDesVirgules
OU (dans le cas d’un script)
Cmnd_Alias NomDeVotreAlias = NomDeVotreAlias /chemin/vers/votre/script/
Le script s’exécutant « en tant que » root vous ne devriez pas avoir de souci de droits, dans le cas contraire :
#: chown www-data:www-data /chemin/vers/votre/script.sh
Vous pouvez également faire plus simple en sautant ces étapes pour directement placer le code suivant dans /etc/sudoers (mais les possibilités de « dérives » vers d’autres utilisations sont moins nombreuses) :
www-data ALL=(ALL) NOPASSWD: /chemin/vers/votre/script.sh
L’exécution du script PHP
Il vous suffira ensuite de lancer la commande grâce à la fonction exec de PHP. Dans le cas ou vous souhaitez relancer Bind sans script (.sh) :
<?PHP exec(‘sudo -u www-data /etc/init.d/bind9 restart’); exit; ?>
Dans le cas ou vous utilisez un script :
<?PHP exec(‘sudo -u www-data /chemin/vers/votre/script.sh’); exit; ?>
Pensez à remplacer www-data par votre utilisateur Apache s’il diffère
Conclusion
Il ne vous reste plus faire un petit formulaire (x)html très simple avec un bouton « Redémarrer Bind » et le tour est joué ! Sachez que cette technique fonctionne même si vous avez Suhosin-patch d’installé.
Si toutefois cette solution ne vous convient pas, il vous reste la solution des scripts SUID, à condition dans ce cas d’avoir solides connaissances en matière de permissions sur les fichiers.
Auteur : Mr Xhark
Fondateur du blog et passionné par les technologies je partage mes découvertes quotidiennement.


(3 vote(s), moy. : 3,33 sur 5)









Déjà 10 commentaires
11 mars 2010 à 9h23
merci, cela m’éclaire. Je n’ai pu identifier l’user apache2 que via la solution no 3.
22 juillet 2010 à 10h44
Mais le reste, tourné dans tous les sens ne marche pas…
j’ai passé plusieurs jours dessus ré exécutant ces mêmes actions: rien
seul www-data ALL=(ALL) NOPASSWD:ALL marche mais n’est pas sécurisé DU TOUT
22 juillet 2010 à 11h36
Après tant de temps passé sur le sujet (si on met tout bout à bout ça fait bien une semaine) pour ma part j’ai enfin réussi…
Mon script à enfin marché quand j’ai enlevé « -u www-data » dans l’exécution du php
ce qui donne
exec(« sudo /chemin_vers_le_script/monscript.sh »);
mais je luis préfère
passthru (« sudo /chemin_vers_le_script/monscript.sh »,$error);
qui me renvoie si il a une erreur
Seul mon script est exécuté et seulement lui
1 septembre 2010 à 18h03
Une solution sale, et si peu sécurisée…
LA bonne méthode, c’est le wrapper :
http://blog.khemael.net/2010/08/26/de-la-maniere-de-faire-de-lexec-et-system-root-en-php/3/
1 septembre 2010 à 18h09
@Tchai : je ne connaissais pas cette méthode des wrappers, merci pour l’info !
27 janvier 2011 à 8h50
Avec ce tuto, est-ce qu’on peut faire de la programmation système avec PHP qui va lancer des applications root comme /etc/init.d/postgresql start?
Merci
14 février 2011 à 10h57
@TTinvent: tout à fait
23 mai 2011 à 16h28
Merci beaucoup pour ce tuto, je vais de ce pas jeter un œil sur le reste du site
24 mai 2011 à 12h45
j’ai installé un serveur XAMPP, donc dans mon cas comment connaitre l’utilisateur qui exécute ce script
22 décembre 2011 à 2h05
@kamal: Tout est dans /xx/lampp/etc/httpd.conf
De mon coté je n’y arrive vraiment pas…
j’ai essayer avec NOPASSWD: ALL, et ça ne marche tout de même pas sous Ubuntu