web-dev-qa-db-fra.com

Exécutez les commandes root via PHP

J'ai un serveur linux CentOS 5.7 et utilise php5.3.x.

Sur un système pfSense, vous pouvez redémarrer des services nécessitant des autorisations root à l'aide d'une page Web php.

J'essaie de faire quelque chose de similaire, j'ai écrit du code PHP pour exécuter des commandes Shell. Par exemple, pour redémarrer le service sshd:

<?php
exec('/sbin/service sshd restart');
?>

et j'ai essayé d'exécuter cette commande via la fonction exec, mais elle nécessite une autorisation root, mais nous avons une autorité utilisateur Apache.

J'ai trouvé quelques solutions:

  1. "exécuter Apache avec l'utilisateur root" vraiment dangereux. Je ne veux pas faire ça.
  2. "Apache ALL = NOPASSWD:/sbin/service pour/etc/sudoers" J'ai essayé mais j'ai toujours un problème.

Toute autre solution? Merci pour les réponses.


maintenant .. c'est intéressant. J'ai essayé @refp post et cela a fonctionné sur mon serveur Ubuntu local. Mais quand j'ai essayé même sur mon serveur cenOS vps. Cela ne fonctionne pas et c'est le journal des erreurs d'Apache "rm: impossible de supprimer`/var/lock/subsys/vsftpd ': Permission refusée "

50
Mehmet INCE

Lisez tout ce post avant de l'essayer, il y a des choix à faire.


Solution utilisant un wrapper binaire (avec suid bit)

1) Créez un script (préférablement .sh) Contenant ce que vous voulez exécuter en tant que root.

# cat > php_Shell.sh <<CONTENT
  #!/bin/sh
  /sbin/service sshd restart
CONTENT

2) Ce fichier doit appartenir à root. Comme il sera exécuté ultérieurement avec des autorisations root, assurez-vous que seul root a l'autorisation d'écrire dans le fichier.

# chown root php_Shell.sh
# chmod u=rwx,go=xr php_Shell.sh

) Pour exécuter le script en tant que root, quel que soit l'utilisateur qui l'exécute, nous avons besoin d'un wrapper binaire. Créez-en un qui exécutera notre php_Shell.sh.

# cat > wrapper.c <<CONTENT
  #include <stdlib.h>
  #include <sys/types.h>
  #include <unistd.h>

  int
  main (int argc, char *argv[])
  {
     setuid (0);

     /* WARNING: Only use an absolute path to the script to execute,
      *          a malicious user might fool the binary and execute
      *          arbitary commands if not.
      * */

     system ("/bin/sh /path/to/php_Shell.sh");

     return 0;
   }
CONTENT

4) Compilez et définissez les autorisations appropriées, y compris le bit suid (indiquant qu'il doit s'exécuter avec les privilèges root):

# gcc wrapper.c -o php_root
# chown root php_root
# chmod u=rwx,go=xr,+s php_root

php_root S'exécutera maintenant avec les permissions root et exécutera les commandes spécifiées dans php_Shell.sh.


Si vous n'avez pas besoin de l'option pour changer facilement les commandes à exécuter, je vous recommande d'écrire les commandes directement dans wrapper.c À l'étape 4. Ensuite, vous n'avez pas besoin qu'un binaire exécute un script externe pour exécuter les commandes en question.

Dans wrapper.c, Utilisez system ("your Shell command here"); pour spécifier les commandes à exécuter.

88

Je n’aurais pas PHP exécuté aucune commande Sudo. Cela me fait penser à des problèmes. Je créerais plutôt deux systèmes distincts.

Le premier système, dans PHP (le niveau Web), traiterait les demandes des utilisateurs. Lorsqu'une demande nécessitant une commande Sudo, je placerais cette demande dans une file d'attente. Il pourrait s'agir d'une base de données de quelque sorte ou middle-ware tel que ZeroMQ.

Le second système (le niveau métier) lirait ou recevrait des messages de cette file d'attente et aurait la possibilité d'exécuter des commandes Sudo, mais ne ferait pas partie du processus de votre serveur Web.

Je sais que c'est un peu vague et qu'il peut être résolu de différentes manières avec différentes technologies, mais je pense que c'est la meilleure et la plus sûre des solutions.

22
Luke

Autorisez l'utilisateur www-data à exécuter program1 et program2 sans mot de passe:

Sudo visudo

Ajoutez au contenu du fichier sudoers:

User_Alias WWW_USER = www-data
Cmnd_Alias WWW_COMMANDS = /sbin/program1, /sbin/program2
WWW_USER ALL = (ALL) NOPASSWD: WWW_COMMANDS

Sauver.

de https://askubuntu.com/questions/76920/call-a-Shell-script-from-php-run-as-root

8
harrrrrrry

Solution utilisant un wrapper binaire (avec suid bit) Une modification de Filip Roséen - refp post.

Pour exécuter toute commande modifiée wrapper.c

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

int main (int argc, char  **argv)
{
 setuid (0);
 char cmd[100] = "";
 int i;
 char *p;
 for(i=0; i < argc; i++) {
    if(i != 0){
   strcat(cmd, *(argv+i));
   strcat(cmd, " ");
    }
 }

 system (cmd);

 return 0;
 }

Compiler et définir les autorisations appropriées;

  gcc wrapper.c -o php_root     # php_root can be any name.
  chown root php_root
  chmod u=rwx,go=xr,+s php_root

Maintenant, appelez depuis PHP. Exécutez n'importe quelle commande.

 Shell_exec('./php_root '.$cmd);//execute from wrapper
2
sharif143

J'ai récemment publié un projet qui permet à PHP d'obtenir et d'interagir avec un vrai shell Bash, il vous donnera facilement un shell connecté en tant que root. Vous pouvez ensuite exécuter les commandes individuelles bash plutôt que regrouper ensuite dans un script. Ainsi, vous pouvez également gérer le retour. Obtenez-le ici: https://github.com/merlinthemagic/MTS

Après le téléchargement, vous utiliserez simplement le code suivant:

$Shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $Shell->exeCmd('service sshd restart');

echo $return1;

//On CentOS 7 output would be like: 
//Redirecting to /bin/systemctl restart  sshd.service

//On CentOS 6 and lower output would be like:
//Stopping sshd:                                             [  OK  ]
//Starting sshd:                                             [  OK  ]
2
MerlinTheMagic