Ejecutar comandos root a través de PHP


Tengo un servidor linux CentOS 5.7 y uso php5.3.x.

En un sistema pfSense, puede reiniciar los servicios-que requieren permisos de root utilizando una página web php.

Estoy tratando de hacer algo similar, he escrito código php para ejecutar comandos de shell. Por ejemplo, para reiniciar el servicio sshd:

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

Y traté de ejecutar ese comando a través de la función exec, pero necesita permiso de root, pero tenemos una autoridad de usuario Apache.

Me he encontrado con algunos soluciones:

  1. " ejecutar apache con usuario root" realmente inseguro. No quiero hacer eso.
  2. " apache ALL=NOPASSWD: / sbin / service to / etc / sudoers" Lo intenté pero aún tengo un problema.

¿Alguna otra solución? Gracias por las respuestas.


Ahora.. es interesante. probé @refp post y funcionó mi servidor ubuntu local. Pero cuando lo intenté en mi servidor cenOS vps. No está funcionando.y ese es el registro de errores de Apache "rm: cannot remove '/var/lock/subsys / vsftpd': Permiso denegado "

Author: Tim Post, 2011-12-16

5 answers

Lea todo este post antes de probarlo, hay opciones que tomar.


Solución usando una envoltura binaria (con bit suid)

1) Cree un script (preferentemente .sh) que contenga lo que desea que se ejecute como root.

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

2) Este archivo debería ser propiedad de root, y dado que más tarde se ejecutará con permisos de root, asegúrese de que solo root tenga permiso para escribir en el archivo.

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

3) Para correr el script como root no importa qué usuario lo ejecute, necesitaremos un wrapper binario. Crear uno que ejecutará nuestro 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) Compilar y establecer los permisos adecuados, incluyendo el bit suid (diciendo que debería ejecutarse con privilegios de root):

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

php_root ahora se ejecutará con permisos de root y ejecutará los comandos especificados en php_root.sh.


Si no necesita la opción para cambiar fácilmente qué comandos se ejecutarán, le recomendaría escribir los comandos directamente en wrapper.c bajo paso 4. Entonces no necesita tener un binario ejecutando un script externo ejecutando los comandos en cuestión.

En wrapper.c, use system ("your shell command here"); para especificar qué comandos desea ejecutar.

 86
Author: Filip Roséen - refp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-01 12:21:22

No haría que PHP ejecutara ningún comando sudo. Para mí eso suena como buscar problemas. En su lugar, crearía dos sistemas separados.

El primer sistema, en PHP (el nivel web), manejaría las solicitudes de los usuarios. Cuando se realiza una solicitud que necesita un comando sudo, colocaría esta solicitud en alguna cola. Esto podría ser una base de datos de algún tipo o middle-ware como ZeroMQ.

El segundo sistema (el nivel de negocio) leería o recibiría mensajes de esta cola y tendría capacidad para ejecutar comandos sudo, pero no estará en el alcance de su proceso de servidor web.

Sé que esto es un poco vago y se puede resolver de diferentes maneras con varias tecnologías, pero creo que esta es la mejor y más segura manera de hacerlo.

 21
Author: Luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-19 02:59:39

Permitir que el usuario www-data ejecute para ejecutar program1 y program2 sin contraseña:

sudo visudo

Añadir al contenido del archivo sudoers:

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

Guardar.

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

 4
Author: harrrrrrry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 12:22:38

Recientemente publiqué un proyecto que permite a PHP obtener e interactuar con un shell Bash real, que le dará fácilmente un shell conectado como root. Entonces puede ejecutar los comandos bash individuales en lugar de agruparlos en un script. De esa manera también puede manejar la devolución. Consíguelo aquí: https://github.com/merlinthemagic/MTS

Después de descargar, simplemente usaría el siguiente código:

$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
Author: MerlinTheMagic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-22 16:55:55

Solución usando una envoltura binaria (con bit suid) Algunas modificaciones de Filip Roséen - refp post.

Para ejecutar cualquier comando modified 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;
 }

Compilar y establecer permisos adecuados;

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

Ahora llama desde PHP. Ejecuta cualquier orden.

 shell_exec('./php_root '.$cmd);//execute from wrapper
 2
Author: sharif143,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-11 05:20:20