2012-07-24 48 views
6

Tengo una pregunta "simple": ¿cómo puedo cambiar de forma segura la contraseña de un script PHP, sin otorgar privilegios de root a Apache ni introducir otros locos agujeros de seguridad?Cambiar la contraseña de usuario de Linux del script PHP

Antecedentes: CentOS 6, Apache 2.2.13, PHP 5.3.3

Soy consciente del comando pam_chpasswd(), que es parte de la biblioteca PECL PAM. Sin embargo, esta función falla a menos que el proceso de host (httpd) tenga acceso de lectura al archivo/etc/shadow. (¡MALA IDEA! No estoy seguro de cómo esta biblioteca ayuda si requiere tantos privilegios ...)

La situación ideal, hasta donde puedo ver, es hacer que PHP invoque un script de shell con 'sudo -u [nombre de usuario de usuario cambiando su contraseña] ' Esto ejecutaría el script "AS" del usuario, por lo que debería tener permiso para cambiar su propia contraseña. Y sudo requeriría que el usuario envíe su contraseña existente para poder ser autenticado, evitando así que un usuario cambie la contraseña de otro usuario.

Pero esto no funciona por alguna razón ... al abrir el proceso con popen, el proceso nunca se ejecuta. Tengo el script de shell configurado para volcar algún texto en un archivo de escritura pública en/tmp. Pero nunca llega a ese punto.

$cmd = "/usr/bin/sudo -S -u$username /file_to_execute.sh"; 
$handle = popen ($cmd, "w"); // Open the process for writing 
fwrite ($handle, "$current_password\n"); // Send the user's current password to sudo (-S option) 
fwrite .... (write the username, current password, and new password, so the script can change it) 
$result = pclose($handle); 

Si accedo a este script php (http: //server/script.php), la función falla inmediatamente, y $ resultado = 1

Si modifico el archivo sudoers (visudo) y añadir una línea:
$ predeterminados: Apache requiretty

El guión se congela durante unos 10 segundos, y luego falla ($ resultado = 1)

¿Alguna sugerencia para hacer esto son muy apreciadas!

+0

Cualquiera de estos trabajos? http://stackoverflow.com/questions/127459/using-shell-execpasswd-to-change-a-users-password?rq=1 – Aknosis

Respuesta

0

Una forma más segura de hacer esto es para almacenar nombre de usuario y contraseña en un archivo en un directorio especial y dejar que cron hacer el trabajo (una vez por minuto)

+0

Gracias por su respuesta. Sin embargo, esto presenta 2 problemas: 1) El usuario no puede obtener comentarios inmediatos sobre si se cambió su contraseña. 2) La contraseña actual del usuario no está verificada. Parece que esto puede no ser demasiado seguro.Quiero que se le solicite al usuario que proporcione su contraseña actual para cambiar la contraseña. Esto evita que cualquier tipo de secuestro por parte de un usuario cambie la contraseña de otro usuario. –

2

Para lograr lo anterior con la seguridad en mente, lo haría sugiera el uso de expect o agregar el usuario de Apche a un grupo que tenga acceso de escritura a dicho archivo y solo a dicho archivo.

Con esperan, tendrá que incluir su contraseña sudo, ya que estará atento a la respuesta del sistema operativo de Password:, y cuando se ve, que responde automáticamente con la contraseña sudo. Esto le permitiría formar un equipo de shell_exec() y familia con expect para lograr sus resultados.

Iría a la segunda ruta de seguridad, que usaría un permiso de grupo para escribir en el archivo de un grupo que solo tiene acceso de escritura a ese archivo.

Ejemplo:

groupadd secure_apache 
usermod -G secure_apache apache_user 
chown owner:secure_apache /tmp/file_to_change 
chmod 740 /tmp/file_to_change 
+0

¿Funcionará el # 2 en un entorno multiusuario? es decir, ¿varios usuarios intentan cambiar sus contraseñas simultáneamente? ¿Asumo que cada solicitud de cambio de contraseña tendría que crear un archivo con un nombre aleatorio para evitar que los usuarios se pisen el uno al otro durante el proceso ...? –

+0

Estoy pensando que la opción "esperar" puede ser mi mejor opción ... –

+1

Si opta por la segunda opción, puede implementar un 'flock()' para bloquear el archivo cuando el primer usuario lo intente. Cuando se completen, elimine el 'flock()' y los demás usuarios pueden ir. Al menos, los otros usuarios recibirán un mensaje de error diciendo que no pueden hacerlo en este momento. –

Cuestiones relacionadas