¿Cómo proteger las contraseñas de bases de datos en PHP?


Cuando una aplicación PHP hace una conexión a la base de datos, por supuesto, generalmente necesita pasar un nombre de usuario y una contraseña. Si estoy usando un único login de permiso mínimo para mi aplicación, entonces el PHP necesita saber ese login y contraseña en alguna parte. ¿Cuál es la mejor manera de asegurar esa contraseña? Parece que simplemente escribirlo en el código PHP no es una buena idea.

Author: AviD, 2008-09-19

17 answers

Varias personas malinterpretan esto como una pregunta sobre cómo almacenar contraseñas en una base de datos. Eso está mal. Se trata de cómo almacenar la contraseña que le permite obtener a la base de datos.

La solución habitual es mover la contraseña del código fuente a un archivo de configuración. Luego deje la administración y la seguridad de ese archivo de configuración en manos de los administradores del sistema. De esta manera, los desarrolladores no necesitan saber nada sobre las contraseñas de producción, y no hay registro de la contraseña en su fuente-control.

 209
Author: user11318,
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
2011-11-07 19:51:47

Si está alojando en el servidor de otra persona y no tiene acceso fuera de su webroot, siempre puede poner su contraseña y/o conexión a la base de datos en un archivo y luego bloquear el archivo utilizando un .htaccess:

<files mypasswdfile>
order allow,deny
deny from all
</files>
 94
Author: kellen,
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
2009-08-03 18:28:18

Almacenarlos en un archivo fuera de la raíz web.

 36
Author: da5id,
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
2008-09-18 23:32:18

La forma más segura es no tener la información especificada en su código PHP en absoluto.

Si estás usando Apache eso significa establecer los detalles de conexión en tu httpd.conf o archivo de hosts virtuales. Si lo hace, puede llamar a mysql_connect () sin parámetros, lo que significa que PHP nunca mostrará su información.

Así es como se especifican estos valores en esos archivos:

php_value mysql.default.user      myusername
php_value mysql.default.password  mypassword
php_value mysql.default.host      server

Entonces abres tu conexión mysql así:

<?php
$db = mysqli_connect();

O similar esto:

<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
                     ini_get("mysql.default.password"),
                     ini_get("mysql.default.host"));
 36
Author: Lars Nyström,
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
2013-11-21 14:42:21

Para sistemas extremadamente seguros ciframos la contraseña de la base de datos en un archivo de configuración (que a su vez está protegido por el administrador del sistema). Al iniciar la aplicación / servidor, la aplicación solicita al administrador del sistema la clave de descifrado. La contraseña de la base de datos se lee desde el archivo de configuración, se descifra y se almacena en la memoria para su uso futuro. Todavía no es 100% seguro, ya que se almacena en la memoria descifrada, pero usted tiene que llamarlo 'lo suficientemente seguro' en algún momento!

 33
Author: pdavis,
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
2008-09-19 13:33:51

Esta solución es general, ya que es útil tanto para aplicaciones de código abierto como para aplicaciones de código cerrado.

  1. Cree un usuario del sistema operativo para su aplicación. Véase http://en.wikipedia.org/wiki/Principle_of_least_privilege
  2. Cree una variable de entorno del sistema operativo (sin sesión) para ese usuario, con la contraseña
  3. Ejecute la aplicación como ese usuario

Ventajas:

  1. No comprobará sus contraseñas en el control de código fuente por accidente, porque no puede
  2. No arruinará accidentalmente los permisos de archivo. Bueno, podrías, pero no afectará esto.
  3. Solo puede ser leído por root o por ese usuario. Root puede leer todos sus archivos y claves de cifrado de todos modos.
  4. Si utiliza cifrado, ¿cómo almacena la clave de forma segura?
  5. Funciona x-platform
  6. Asegúrese de no pasar el envvar a procesos hijos no confiables

Este método es sugerido por Heroku, que son muy exitosos.

 13
Author: Neil McGuigan,
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-04-26 16:20:46

Si es posible crear la conexión de la base de datos en el mismo archivo donde se almacenan las credenciales. Inserta las credenciales en la instrucción connect.

mysql_connect("localhost", "me", "mypass");

De lo contrario, es mejor desajustar las credenciales después de la instrucción connect, porque las credenciales que no están en memoria, no se pueden leer desde la memoria ;)

include("/outside-webroot/db_settings.php");  
mysql_connect("localhost", $db_user, $db_pass);  
unset ($db_user, $db_pass);  
 11
Author: Bob Fanger,
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-05-19 05:49:50

Sus opciones son un poco limitadas ya que, como usted dice, necesita la contraseña para acceder a la base de datos. Un enfoque general es almacenar el nombre de usuario y la contraseña en un archivo de configuración separado en lugar del script principal. A continuación, asegúrese de almacenar que fuera del árbol web principal. Eso fue si hay un problema de configuración web que deja que sus archivos php se muestren simplemente como texto en lugar de ejecutarse, no ha expuesto la contraseña.

Aparte de eso, estás en las líneas correctas con acceso mínimo para la cuenta que se está utilizando. Añadir a eso

  • No use la combinación de nombre de usuario / contraseña para nada más
  • Configure el servidor de base de datos para que solo acepte conexiones del servidor web para ese usuario (localhost es aún mejor si la base de datos está en la misma máquina) De esa manera, incluso si las credenciales están expuestas, no son útiles para nadie a menos que tengan otro acceso a la máquina.
  • Ofuscar la contraseña (incluso ROT13 hará) no va a poner mucho defensa si algunos tienen acceso al archivo, pero al menos evitará la visualización casual del mismo.

Peter

 7
Author: Vagnerr,
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
2008-09-18 23:36:03

Creo que el OP significa la contraseña de la base de datos.

A menos que alguien obtenga acceso a su servidor a través de FTP o SSH (en cuyo caso ya está jodido), no me preocuparía por almacenar contraseñas en texto plano en archivos PHP. La mayoría de las aplicaciones PHP que he visto lo hacen de esa manera, por ejemplo phpbb.

 5
Author: Ryan Bigg,
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
2008-09-18 23:31:52

Ponga la contraseña de la base de datos en un archivo, hágalo de solo lectura para el usuario que sirve los archivos.

A menos que tenga algún medio de permitir solo que el proceso del servidor php acceda a la base de datos, esto es prácticamente todo lo que puede hacer.

 5
Author: Chris,
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
2008-09-18 23:32:40

Si está utilizando PostgreSQL, entonces busca en ~/.pgpass contraseñas automáticamente. Vea el manual para más información.

 5
Author: Jim,
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
2008-09-18 23:52:43

Si está hablando de la contraseña de la base de datos, en lugar de la contraseña que proviene de un navegador, la práctica estándar parece ser poner la contraseña de la base de datos en un archivo de configuración PHP en el servidor.

Solo necesita estar seguro de que el archivo php que contiene la contraseña tiene los permisos apropiados en él. Es decir, solo debe ser legible por el servidor web y por su cuenta de usuario.

 4
Author: Jason Wadsworth,
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
2008-09-18 23:35:09

Anteriormente almacenamos el usuario/pase de la base de datos en un archivo de configuración, pero desde entonces hemos golpeado el modo paranoico adopting adoptando una política de Defensa en Profundidad.

Si su aplicación está comprometida, el usuario tendrá acceso de lectura a su archivo de configuración y, por lo tanto, existe la posibilidad de que un cracker lea esta información. Los archivos de configuración también pueden quedar atrapados en el control de versiones o copiados alrededor de servidores.

Hemos cambiado a almacenar las variables de entorno user / pass in establecidas en el Apache VirtualHost. Esta configuración solo es legible por root hopefully esperemos que su usuario Apache no se esté ejecutando como root.

La desventaja con esto es que ahora la contraseña está en una variable PHP Global.

Para mitigar este riesgo tenemos las siguientes precauciones:

  • La contraseña está encriptada. Extendemos la clase PDO para incluir la lógica para descifrar la contraseña. Si alguien lee el código donde establecemos una conexión, no será obvio que la conexión se establece con una contraseña cifrada y no con la contraseña en sí.
  • La contraseña cifrada se mueve de las variables globales a una variable privada La aplicación hace esto inmediatamente para reducir la ventana que el valor está disponible en el espacio global.
  • phpinfo() está desactivado. PHPInfo es un objetivo fácil para obtener una visión general de todo, incluidas las variables de entorno.
 4
Author: Courtney Miles,
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-02-15 02:41:48

Un truco adicional es usar un archivo de configuración separado de PHP que se vea así:

<?php exit() ?>

[...]

Plain text data including password

Esto no le impide establecer reglas de acceso correctamente. Pero en el caso de que su sitio web sea hackeado, un "require" o un "include" simplemente saldrá del script en la primera línea, por lo que es aún más difícil obtener los datos.

Sin embargo, no permita nunca que los archivos de configuración estén en un directorio al que se pueda acceder a través de la web. Debe tener una carpeta " Web " que contenga su controlador código, css, imágenes y js. Eso es todo. Cualquier otra cosa va en carpetas sin conexión.

 3
Author: e-satis,
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
2008-09-19 13:08:18

La mejor manera es no almacenar la contraseña en absoluto!
Por ejemplo, si está en un sistema Windows y se conecta a SQL Server, puede usar la autenticación integrada para conectarse a la base de datos sin contraseña, utilizando la identidad del proceso actual.

Si necesita conectarse con una contraseña, primero cifrarla, utilizando un cifrado fuerte (por ejemplo, utilizando AES-256, y luego proteger la clave de cifrado, o utilizando un cifrado asimétrico y hacer que el sistema operativo proteja el cert), y luego almacenarlo en un archivo de configuración (fuera del directorio web) con ACL fuertes.

 3
Author: AviD,
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
2008-09-20 21:17:12

Simplemente colocarlo en un archivo de configuración en algún lugar es la forma en que generalmente se hace. Solo asegúrese de que:

  1. no permitir el acceso a la base de datos desde cualquier servidor fuera de su red,
  2. tenga cuidado de no mostrar accidentalmente la contraseña a los usuarios (en un mensaje de error, o a través de archivos PHP que se sirven accidentalmente como HTML, etc.)
 3
Author: Marijn,
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-03-10 03:14:41

Lo hemos resuelto de esta manera:

  1. Use memcache en el servidor, con conexión abierta desde otro servidor de contraseñas.
  2. Guarde en memcache la contraseña (o incluso toda la contraseña).php file encrypted) más la clave de descifrado.
  3. El sitio web, llama a la clave memcache que contiene la frase de contraseña del archivo de contraseña y descifra en memoria todas las contraseñas.
  4. El servidor de contraseñas envía un nuevo archivo de contraseña cifrado cada 5 minutos.
  5. Si utiliza una contraseña cifrada.php en su proyecto, se pone una auditoría, que comprobar si este archivo se tocó externamente-o visto. Cuando esto sucede, puede limpiar automáticamente la memoria, así como cerrar el servidor para acceder.
 3
Author: Asi Azulay,
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-08-28 16:27:10