2010-11-12 55 views
5

comment autoriser un script PHP à exécuter un script bash avec des permissions root?Autoriser PHP à exécuter un script bash avec les permissions root

Disons qu'il est un script PHP ...

<?php 
// location: /var/www/script.php 
exec("bash /var/scripts/test.sh"); // "sudo bash ..." does not work 
?> 

et un script bash ...

#!/bin/bash 
# location: /var/scripts/test.sh 
sudo mkdir /test 

Bien sûr PHP et Apache ne doit pas fonctionner en tant que root et au mieux la Le script peut être exécuté avec les permissions root. Des idées?

Meilleures salutations, Jimbo

+4

Pourquoi avez-vous besoin que le script s'exécute avec les permissions root? Pourriez-vous modifier les ressources auxquelles il accède pour qu'il soit lisible (et si nécessaire inscriptible) par l'utilisateur qu'Apache exécute actuellement? – meagar

+0

Non. Je voudrais exécuter un 'git pull' et un' a2dissite'/'a2ensite'. – Jimbo

Répondre

6

Toute solution basée sur PHP qui donne les droits root à un moment donné de la chaîne est dangereuse: Un attaquant ayant accès à l'utilisateur PHP peut accéder à l'utilisateur root, et qui est inacceptable du point de vue de la sécurité.

Je ne l'ai jamais implémenté moi-même, mais je suggérerai ce que j'ai suggéré here: Avoir un script/travail cron avec droits root scanne fréquemment un emplacement pour un signe du script PHP qu'un travail doit être fait - pour exemple, un fichier avec un certain nom ou une entrée dans une base de données d'emplois.

Si ce fichier est trouvé exister, le script racine fait sa chose, et supprime le fichier à nouveau.

Si votre script PHP n'a pas besoin de réponse directe du script racine, je pense que ce serait la meilleure solution. (Une réponse pourrait aussi être facilitée par le script racine qui écrit un message d'état dans le fichier, bien sûr).

Tant que vous limitez de près les types de tâches que PHP peut écrire pour le script racine, cette solution est une solution étanche, car elle ne fait pas entrer l'utilisateur racine dans l'activité de PHP.

+0

J'ai cette solution en cours d'exécution pour le moment. Je me demandais s'il y avait des solutions aussi sûres que le script/crontab mais plus rapides, plus efficaces et permettant une réponse directe. Juste comme frapper un domino. – Jimbo

+0

@Jimbo - vous voulez dire exécuter php + apache plus vite que la commande shell? ou u signifie plus pratique? – ajreal

+0

Non. Je veux dire sans attendre que le travail de cron commence. – Jimbo

1

Vous n'avez pas besoin de PHP ou d'Apache pour s'exécuter en tant que root. Si vous avez le contrôle de votre serveur, vous pouvez utiliser un module Apache appelé suPHP et spécifier l'utilisateur que vous voulez exécuter Apache comme pour vos scripts php dans la configuration. Vous pouvez le faire site par site, vous n'avez donc qu'à lancer suPHP pour les scripts sur un domaine particulier. Je n'ai pas l'expertise pour vous conseiller sur la façon de l'installer, mais j'ai demandé à notre société de serveur dédiée de permettre à un hook post-réception de github d'appeler un script sur mon serveur de dev pour déclencher une git pull au serveur dev temps quelqu'un pousse à la repos github. J'ai été incapable de le faire fonctionner autrement puisque Apache doit fonctionner en tant que propriétaire du repos local pour que cela fonctionne. Je viens de penser à une autre solution possible basée sur les autres commentaires ici - vous pourriez écrire un simple script php pour recevoir la requête du hook github et écrire des informations arbitraires dans un répertoire 777 autorisations ou à la DB. Ensuite, ayez un travail cron qui vérifie chaque fichier ou db chaque minute pour voir si elle a changé et si c'est le cas, lancez la requête git pull directement car cron s'exécute généralement en tant que root. Vous pouvez même voir si l'horodatage du fichier a changé pour déterminer s'il faut faire le git pull. Vous pourriez avoir votre script cron su à n'importe quel utilisateur possédé les repos et émettre le git pull alors. Pas une vraie solution en temps réel, mais si le script cron est très simple, il n'encombrerait pas votre système pour l'appeler toutes les minutes ou deux. J'espère que cela pourra aider.

6

Si vous ne voulez pas attendre cron, voici un simple wrapper en C, que vous appellerez php.

#include <unistd.h> 
#include <errno.h> 
#define WEBUID 500 
main(int argc, char ** argv, char ** envp) { 
    if(getuid() != WEBUID) exit(1); 
    /* some more security checks */ 
    if(setuid(geteuid())) perror("setuid error"); 
    envp = 0; /* don't want environment - security problem */ 
    system("/hardcoded/path/to/script.bash", argv, envp); 
} 

Cette enveloppe doit être compilé propriété en tant que root, groupe « www » et devrait avoir « s bits ».
chwon root.www wrapper; chmod 4440 wrapper, si

  • quand est exécuté son UID effectif sera racine
  • exécuter peut seul groupe www (groupe de serveur web)
  • et quand l'UID de l'appelant n'est pas un Web- le serveur va quitter
+0

Fonctionne un régal! Quelle belle réflexion en dehors de la boîte, merci. – georgiecasey

2

Vous devez jeter un oeil à incron (cron pour les événements du système de fichiers). Avoir le php écrire dans un fichier et définir incron pour lancer votre script à la fermeture de l'écrit dans le fichier (incron est très spécifique). Votre script devrait probablement également désinfecter le fichier d'entrée pour empêcher l'injection de code et utiliser également la commande lockfile pour empêcher toute situation de concurrence entre plusieurs utilisateurs Web.

J'ai une mini-interface web où l'on peut activer FTP anonyme ou d'autres services pendant 1 heure avec un mot de passe. www fonctionne avec des privilèges normaux, tout comme www-data (l'utilisateur php) mais incron appelle le script de gestion des entrées en tant que root.

Mike

0

Utilisez un démon en cours d'exécution en tant que root (peut-être écrit en C), qui commence les scripts shell pour vous. Pour déclencher l'exécution du script shell à partir du script PHP, utilisez simplement IPC (files d'attente de messages).

Jetez un oeil ici pour avoir une idée de ce que je parle: http://php.net/manual/en/function.msg-send.php#114831

0

I a récemment publié un projet qui permet à PHP d'obtenir et d'interagir avec un shell réel Bash (en tant que root sur demande), il résout le limitations de exec() et shell_exec(). Obtenez ici: https://github.com/merlinthemagic/MTS

Après avoir téléchargé vous suffit d'utiliser le code suivant:

$shell = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true); 
$return1 = $shell->exeCmd('/my/bash/script.sh'); 
//the return will be a string containing the return of the command 
echo $return1; 

En termes de sécurité, il est beaucoup mieux que de courir apache en tant que root. Mais laisser PHP n'importe où près de la racine est toujours délicat.

Le projet i construit réalise un shell bash racine dans l'une des 2 façons:

1) Vous permettez apache le droit de sudo python.

OU

2) Vous passez des informations d'identification de la racine à l'objet chaque fois que vous avez besoin d'un shell avec la configuration de la racine.

Choisissez votre poison. :) Lisez la documentation.