password - login con contraseña encriptada php
¿Cómo asegurar las contraseñas de bases de datos en PHP? (17)
¡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 una contraseña, utilizando la identidad del proceso actual.
Si necesita conectarse con una contraseña, primero debe cifrarla , usando una encriptación fuerte (por ejemplo, utilizando AES-256, y luego proteger la clave de encriptación, o usar una encriptación asimétrica y hacer que el sistema operativo proteja el certificado), y luego almacenarla en una Archivo de configuración (fuera del directorio web) con ACL fuertes .
Por supuesto, cuando una aplicación PHP realiza una conexión de base de datos, generalmente necesita pasar un nombre de usuario y contraseña. Si estoy usando un inicio de sesión con un permiso mínimo para mi aplicación, entonces el PHP debe conocer ese inicio de sesión y la contraseña en algún lugar. ¿Cuál es la mejor manera de asegurar esa contraseña? Parece que solo escribirlo en el código PHP no es una buena idea.
Almacenarlos en un archivo fuera de la raíz web.
Anteriormente almacenábamos el usuario / paso de la base de datos en un archivo de configuración, pero desde entonces hemos alcanzado el modo paranoico, 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, por lo que 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 copiarse en servidores.
Hemos cambiado a almacenar las variables de entorno user / pass en el Apache VirtualHost. Esta configuración solo es legible por root, es de esperar que su usuario de Apache no se esté ejecutando como root.
La contra con esto es que ahora la contraseña está en una variable global de PHP.
Para mitigar este riesgo tenemos las siguientes precauciones:
- La contraseña está encriptada. Extendemos la clase PDO para incluir 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 está estableciendo 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 lo hace de inmediato para reducir la ventana de que el valor está disponible en el espacio global.
-
phpinfo()
está deshabilitado. PHPInfo es un objetivo fácil de obtener una visión general de todo, incluidas las variables de entorno.
Coloque la contraseña de la base de datos en un archivo, haga que sea de solo lectura para el usuario que sirve los archivos.
A menos que tenga alguna forma de permitir que el proceso del servidor php acceda a la base de datos, esto es todo lo que puede hacer.
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á fastidiado), no me preocuparía almacenar las 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.
Esta solución es general, ya que es útil para aplicaciones de código abierto y cerrado.
- Crea un usuario de sistema operativo para tu aplicación. Ver http://en.wikipedia.org/wiki/Principle_of_least_privilege
- Cree una variable de entorno del sistema operativo (sin sesión) para ese usuario, con la contraseña
- Ejecuta la aplicación como ese usuario.
Ventajas:
- No revisará sus contraseñas en el control de la fuente por accidente, porque no puede
- No arruinarás accidentalmente los permisos de archivos. Bueno, podrías, pero no afectará esto.
- Solo puede ser leído por root o ese usuario. Root puede leer todos tus archivos y claves de cifrado de todos modos.
- Si utiliza el cifrado, ¿cómo almacena la clave de forma segura?
- Funciona la plataforma x
- Asegúrese de no pasar el envvar a procesos secundarios no confiables
Este método es sugerido por Heroku, que tiene mucho éxito.
La forma más segura es no tener la información especificada en su código PHP en absoluto.
Si está utilizando Apache, eso significa configurar los detalles de conexión en su archivo httpd.conf o hosts virtuales. Si lo hace, puede llamar a mysql_connect () sin parámetros, lo que significa que PHP nunca emitirá 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 así:
<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
ini_get("mysql.default.password"),
ini_get("mysql.default.host"));
Lo hemos resuelto de esta manera:
- Use memcache en el servidor, con conexión abierta desde otro servidor de contraseñas.
- Guarde en memcache la contraseña (o incluso todo el archivo password.php cifrado) más la clave de descifrado.
- El sitio web, llama a la clave memcache que contiene la contraseña del archivo de contraseña y descifra en la memoria todas las contraseñas.
- El servidor de contraseñas envía un nuevo archivo de contraseñas cifradas cada 5 minutos.
- Si está utilizando password.php cifrado en su proyecto, coloca una auditoría que comprueba si este archivo se tocó externamente o si se vio. Cuando esto sucede, automáticamente puede limpiar la memoria, así como cerrar el servidor para el acceso.
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 le solicita al administrador del sistema la clave de descifrado. La contraseña de la base de datos luego se lee del archivo de configuración, se descifra y se almacena en la memoria para su uso futuro. ¡Aún no está 100% seguro ya que está almacenado en la memoria desencriptada, pero debe llamarlo "lo suficientemente seguro" en algún momento!
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 de base de datos en un archivo y luego bloquear el archivo con un .htaccess:
<files mypasswdfile>
order allow,deny
deny from all
</files>
Si está hablando de la contraseña de la base de datos, a diferencia de la contraseña que proviene de un navegador, la práctica estándar parece ser colocar la contraseña de la base de datos en un archivo de configuración de PHP en el servidor.
Solo debe asegurarse de que el archivo php que contiene la contraseña tenga los permisos adecuados. Es decir, debe ser legible solo por el servidor web y por su cuenta de usuario.
Si está usando PostgreSQL, entonces busca contraseñas en ~/.pgpass
automáticamente. Consulte el manual para más información.
Solo ponerlo en un archivo de configuración en alguna parte es la forma en que normalmente se hace. Sólo asegúrate de que:
- no permitir el acceso a la base de datos desde cualquier servidor fuera de su red,
- 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.)
Sus opciones son limitadas, ya que dice que 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 de la secuencia de comandos principal. A continuación, asegúrese de almacenar eso 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á en las líneas correctas con acceso mínimo para la cuenta que se está utilizando. Añadir a eso
- No uses la combinación de nombre de usuario / contraseña para nada más.
- Configure el servidor de la base de datos para que solo acepte conexiones desde el host web para ese usuario (localhost es incluso mejor si la base de datos está en la misma máquina) De esa manera, incluso si las credenciales están expuestas, no sirven para nadie a menos que tengan otro acceso al máquina.
- Ofuscando la contraseña (incluso ROT13 sí lo hará) no ofrecerá mucha defensa si algunos obtienen acceso al archivo, pero al menos evitará que se vea.
Peter
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 configurar correctamente las reglas de acceso. Pero en el caso de que su sitio web sea hackeado, un "requerimiento" o un "incluir" simplemente saldrá del script en la primera línea, por lo que es aún más difícil obtener los datos.
Sin embargo, nunca deje archivos de configuración en un directorio al que se pueda acceder a través de la web. Debe tener una carpeta "Web" que contenga su código de control, css, imágenes y js. Eso es todo. Todo lo demás va en carpetas sin conexión.
Varias personas lo interpretan incorrectamente 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 acceder 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 de su sistema. De esa manera, los desarrolladores no necesitan saber nada acerca de las contraseñas de producción, y no hay registro de la contraseña en su control de código fuente.
si es posible crear la conexión de la base de datos en el mismo archivo donde se almacenan las credenciales. En línea las credenciales en la declaración de conexión.
mysql_connect("localhost", "me", "mypass");
De lo contrario, es mejor desactivar las credenciales después de la instrucción de conexión, ya que las credenciales que no están en la memoria no se pueden leer de la memoria ;)
include("/outside-webroot/db_settings.php");
mysql_connect("localhost", $db_user, $db_pass);
unset ($db_user, $db_pass);