2010-11-12 38 views
5

cómo permitir que un script PHP ejecute un script bash con permisos de raíz?Permitir que PHP ejecute un script bash con permisos de raíz

Digamos que hay un script PHP ...

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

y una escritura del golpe ...

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

Por supuesto PHP y Apache no se debe ejecutar como root y en sólo el mejor script se puede ejecutar con permisos de root. ¿Algunas ideas?

Saludos, Jimbo

+4

¿Por qué necesita la secuencia de comandos para ejecutar con permisos de raíz? ¿Podría cambiar los recursos a los que está accediendo para que sean legibles (y, si es necesario, modificables) por el usuario con el que Apache se está ejecutando actualmente? – meagar

+0

No. Me gustaría ejecutar un 'git pull' y algunos' a2dissite'/'a2ensite'. – Jimbo

Respuesta

6

Cualquier solución basada en PHP que da derechos de raíz en algún punto de la cadena es peligroso: Un atacante con acceso al usuario PHP podría tener acceso al usuario root, y que es inaceptable desde el punto de vista de la seguridad.

Nunca lo he implementado yo mismo, pero sugiero lo que sugerí here: Tener un script/trabajo cron con derechos de root con frecuencia escanear una ubicación para un signo del script PHP que un trabajo se debe hacer - para ejemplo, un archivo con un cierto nombre o una entrada en una base de datos de trabajos.

Si se encuentra que existe ese archivo, el script raíz hace su trabajo y lo elimina nuevamente.

Si su script PHP no necesita una respuesta directa desde el script raíz, creo que este sería el mejor camino a seguir. (Una respuesta también podría ser facilitada por el script raíz escribiendo un mensaje de estado en el archivo, por supuesto).

Siempre que limite estrechamente los tipos de trabajos que PHP puede escribir para el script raíz, esta es una solución hermética, ya que no hace que el usuario root entre en el negocio de PHP.

+0

Tengo estas soluciones funcionando en este momento. Me preguntaba si hay soluciones que sean tan seguras como la secuencia de comandos/crontab pero más rápidas, más eficientes y que permitan una respuesta directa. Al igual que golpear un dominó. – Jimbo

+0

@Jimbo: ¿te refieres a ejecutar php + apache más rápido que el comando de shell? o u significa más conveniente? – ajreal

+0

No. Quiero decir sin el tiempo de espera hasta que comience el trabajo cron. – Jimbo

1

Es posible que no necesite PHP o Apache para ejecutar como root. Si tiene el control de su servidor, es posible que pueda utilizar un módulo Apache llamado suPHP y especifique el usuario que desea ejecutar Apache para sus scripts php en la configuración. Puede hacerlo sitio por sitio, por lo que solo necesita ejecutar suPHP para las secuencias de comandos en un dominio en particular. No tengo la experiencia para aconsejarle sobre cómo instalarlo, pero hice que nuestra compañía de servidores dedicada me lo hiciera para permitir que un gancho post-recepción de github llamara un script en mi servidor de desarrollo para activar un git pull al servidor de desarrollo. tiempo alguien empuja a los repos de github. No pude hacer que funcionara de otra forma ya que Apache necesita ejecutarse como el propietario de los repositorios locales para que funcione.

Acabo de pensar en otra posible solución basada en los otros comentarios aquí - es posible que pueda escribir un script php simple para recibir la solicitud desde el gancho github y escribir alguna información arbitraria en un archivo en un directorio con 777 permisos o al db. Luego, tenga un trabajo cron que verifique ese archivo o db cada minuto para ver si ha cambiado y, de ser así, emita la solicitud de extracción de git directamente, ya que cron normalmente ya se ejecuta como raíz. Incluso podría ver si la marca de tiempo del archivo ha cambiado para determinar si hacer o no el git pull. Usted podría tener su script cron su para cualquier usuario que posea los repos y luego emitir el git pull. No es una verdadera solución en tiempo real, pero si el script cron es muy simple, no atascaría tu sistema para llamarlo uno o dos minutos. Espero que ayude.

6

Si no quieres esperar a cron, aquí hay un simple contenedor en C, como llamarás desde 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); 
} 

Este envoltorio compilado debe ser propiedad como raíz, el grupo "www" y debe tener "s-bit".
chwon root.www wrapper; chmod 4440 wrapper, por lo

  • cuando se ejecuta su efectiva UID habrá raíz
  • ejecutarlo sólo puede www grupo (grupo de servidor web)
  • y cuando el UID de la persona que llama no es un web- el servidor saldrá de
+0

¡Funciona bien! Qué gran pensamiento fuera de la caja, gracias. – georgiecasey

2

Debe echar un vistazo a incron (cron para los eventos del sistema de archivos). Haga que php escriba en un archivo y configure incron para iniciar su script al cerrar el archivo escrito en el archivo (incron es muy específico). Su secuencia de comandos probablemente también desinfectará el archivo de entrada para evitar la inyección de código y también usará el comando lockfile para evitar cualquier condición de carrera entre múltiples usuarios de la web.

Tengo una interfaz mini web donde se puede activar el FTP anónimo u otros servicios durante 1 hora con una contraseña. www se ejecuta con privilegios normales al igual que www-data (el usuario de php) pero incron llama al script de manejo de entrada como root.

Mike

0

uso de un demonio que se ejecuta como root (tal vez escrito en C), que comienza los scripts de shell para usted. Para activar la ejecución del script de shell dentro del script PHP solo use IPC (colas de mensajes).

un vistazo aquí para tener una idea de lo que estoy hablando: http://php.net/manual/en/function.msg-send.php#114831

0

Hace poco publicó un proyecto que permite a PHP para obtener e interactuar con una cáscara verdadera Bash (como root si se solicita), que resuelve el limitaciones de exec() y shell_exec(). Consíguelo aquí: https://github.com/merlinthemagic/MTS

Después de descargar sólo tendría que utilizar el siguiente código:

$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 términos de seguridad es mucho mejor que con Apache como root. Pero dejar PHP en cualquier lugar cerca de la raíz siempre es complicado.

El proyecto construí logra un intérprete de comandos bash, en una de las 2 formas:

1) Se permiten apache el derecho de pitón sudo.

O

2) Se pasa las credenciales de root para el objeto cada vez que necesita un depósito de configuración de la raíz.

Elija su veneno. :) Lee la documentación.

Cuestiones relacionadas