2012-07-24 14 views
6

Ho una domanda "semplice": come posso modificare in modo sicuro la password di un utente da uno script PHP, senza concedere privilegi di root Apache o introdurre altri buchi di sicurezza pazzi?Modifica password utente Linux da script PHP

Background: CentOS 6, Apache 2.2.13, PHP 5.3.3

Sono consapevole del comando pam_chpasswd(), che è parte della libreria PECL PAM. Tuttavia, questa funzione ha esito negativo a meno che il processo host (httpd) abbia accesso in lettura al file/etc/shadow. (BAD IDEA! Non sono sicuro di come questa libreria sia d'aiuto se richiede privilegi così elevati ...)

La situazione ideale, per quanto posso vedere, è che PHP chiama uno script di shell con 'sudo -u [username di utente che modifica la sua password] ' Questo eseguirà lo script "AS" come utente, quindi dovrebbe avere il permesso di cambiare la propria password. E sudo richiederebbe che l'utente invii la sua password esistente per essere autenticato, impedendo così a un utente di modificare la password di un altro utente.

Ma questo non funziona per qualche motivo ... quando si apre il processo con popen, il processo non viene mai eseguito. Ho impostato lo script della shell per scaricare del testo in un file scrivibile pubblicamente in/tmp. Ma non arriva mai a quel 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); 

Se accedo questo script php (http: //server/script.php), la funzione fallisce immediatamente, e $ risultato = 1

Se modifico il file sudoers (visudo) e aggiungere una linea:
$ Defaults: apache requiretty

Lo script si blocca per circa 10 secondi, poi fallisce ($ risultato = 1)

Eventuali suggerimenti per fare questo sono molto apprezzate!

+0

Qualsiasi di questi lavori? http://stackoverflow.com/questions/127459/using-shell-execpasswd-to-change-a-users-password?rq=1 – Aknosis

risposta

0

Un modo più sicuro per farlo è quello di memorizzare il nome utente e la password in un file in una directory speciale e lasciare cron fare il lavoro (una volta al minuto)

+0

Grazie per la risposta. Tuttavia, questo introduce 2 problemi: 1) L'utente non può ottenere un riscontro immediato se la sua password è stata cambiata. 2) La password esistente dell'utente non è verificata. Sembra che questo non sia troppo sicuro.Desidero che all'utente venga richiesto di fornire la sua password esistente per poter cambiare la password. Ciò impedisce a qualsiasi utente di qualsiasi tipo di dirottamento di modificare la password di un altro utente. –

2

Per realizzare quanto sopra con la sicurezza in mente, vorrei suggerire l'uso di expect o aggiungere l'utente Apche a un gruppo che ha accesso in scrittura a detto file e solo detto file.

Con aspettano, è necessario includere il tuo sudo della password, in quanto sarà in ascolto per la risposta da parte del sistema operativo di Password:, e quando visto, risponde automaticamente con la sudo password. Ciò consentirebbe di associare shell_exec() e famiglia con expect per raggiungere i risultati.

Mi piacerebbe andare al secondo percorso per sicurezza, che userebbe un permesso di gruppo per scrivere sul file per un gruppo che ha solo accesso in scrittura a quel file.

Esempio:

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

Il # 2 funzionerà in un ambiente multiutente? più utenti provano a cambiare le loro password contemporaneamente? Presumo che ogni richiesta di modifica della password dovrebbe creare un file con nomi casuali per evitare che gli utenti si calpestino l'un l'altro durante il processo ...? –

+0

Sto pensando che l'opzione "expect" potrebbe essere la mia migliore scommessa ... –

+1

Se vai con la seconda opzione, puoi implementare un 'flock()' per bloccare il file quando il primo utente prova. Quando sono completati, rimuovere 'flock()' e gli altri utenti possono andare. Altrimenti gli altri utenti riceveranno un errore che dice che al momento non è possibile. –