PHP: se necesita ayuda para cifrar / hash una contraseña para una aplicación pequeña

2

He creado un pequeño script para trabajar. Es un script web interno, pero tiene que estar alojado en nuestro dominio público, por lo que he creado un sistema de inicio de sesión basado en PHP muy pequeño mediante un formulario de inicio de sesión y una verificación de sesión. En lugar de tener que definir la contraseña en texto plano, ¿puede alguien mostrarme cómo agregar la contraseña en un formato cifrado, sin el uso de una base de datos o un archivo externo?

Mi código de inicio de sesión está publicado en la parte inferior, justo encima de la línea en la que me gustaría cambiar esta contraseña a algún tipo de cifrado para que no se pueda leer texto sin formato en caso de que alguien obtenga acceso a los archivos, o PHP se estropee. y comienza a imprimir en texto plano. He intentado googlear y buscar en SE bu todo está relacionado con DBs y archivos conf externos.

$ logins = array ('username' = > 'password123');

    <?php session_start();

if(isset($_POST['Submit'])){
$logins = array('username' => 'password123');


$Username = isset($_POST['Username']) ? $_POST['Username'] : '';
$Password = isset($_POST['Password']) ? $_POST['Password'] : '';


if (isset($logins[$Username]) && $logins[$Username] == $Password){


$_SESSION['UserData']['Username']=$logins[$Username];
  if (isset($_SESSION["login_redirect"])) {
        header("Location: " . $_SESSION["login_redirect"]);
        unset($_SESSION["login_redirect"]);
    } else {
        header("Location: index.php");
    }
exit;
} else {

/* Login failed display message */
$msg="<span style='color:red'>Invalid Login Details</span>";
}
}

¡Gracias por cualquier ayuda!

p.s. El script está alojado / servido desde HTTPS y HTTP2 en PHP 7x y apache en caso de que haga alguna diferencia.

Editar:

Para empezar, solo hay 1 usuario y contraseña. Puede haber usuarios adicionales en el futuro. Pero tal como está ahora, solo se necesita uno para el personal. No hay ningún requisito para registrar acciones del usuario, etc. en este momento.

El script estará en un subdominio de un sitio web público que tiene su propio WAF que también protege al subdirectorio, por lo que se eliminarán cosas como la fuerza bruta. También tenemos Mod Security y CSF en el servidor, lo que también ayudará.

La secuencia de comandos se hospeda en el lado público, ya que la empresa no utiliza un servidor interno de intranet, VPN o LDAP / AD, etc. La secuencia de comandos también debe ser accesible fuera de la oficina, en caso de que el jefe decida trabajar desde su casa o Starbucks ...

Solo quiero asegurar la parte de la contraseña porque está almacenada en texto sin formato dentro del archivo login.php. Si alguien tuviera acceso a él en el servidor o por FTP, etc., tendría un acceso fácil a la contraseña. Y como se mencionó, si PHP se rompe, tampoco quiero que la contraseña se muestre como texto simple en la pantalla.

Así que para actualizar un poco mi pregunta. ¿Alguien puede darme indicadores de inicio para reemplazar la contraseña con un sistema de contraseña hash?

Una vez más, entiendo que varias personas de aquí sugerirán el uso de intranets corporativos, redes privadas virtuales (VPN), plataformas dedicadas, bla, bla, por favor, entiendan que esta es una pequeña empresa y un proyecto aún más pequeño. Cosas como las contraseñas de filtrado de personal son una preocupación menor. Estoy más interesado en asegurar la contraseña que ya existe y en mantener el script lo más pequeño y liviano posible.

    
pregunta Greg 07.09.2018 - 18:18
fuente

3 respuestas

3

Algunos puntos:

  • Las contraseñas deben estar con hash, no encriptadas. El cifrado es reversible; alguien que no debería tener acceso pero que puede ver el código fuente de la aplicación puede encontrar la contraseña cifrada y su clave de cifrado, descifrar la contraseña y, por lo tanto, obtener acceso. Hashes son unidireccionales; no se puede convertir un resumen de hash de nuevo en el texto que se ha cifrado.
    • Lo ideal es que desees una función hash lenta (PBKDF2, bcrypt, scrypt o argon2, con el fin de aumentar la seguridad) porque los hashes rápidos pueden se pueden forzar con gran facilidad con el hardware moderno.
    • Definitivamente querrá usar un hash salado (los algoritmos anteriores esperarán o generarán automáticamente una sal), ya que de lo contrario, un atacante puede usar una tabla de arco iris (o simplemente buscar el resumen de hash en Google) para encontrar la contraseña muy rápidamente. .
  • El sistema que describe es demasiado frágil. Con cada usuario de este sistema compartiendo una contraseña, se se filtrará. Alguien dejará la compañía, o iniciará sesión desde un sistema comprometido, o lo dejará en una nota adhesiva donde no debería, o lo enviará por un canal de comunicación inseguro, o algo así. En otras palabras, no hay una forma muy segura de hacer lo que está pidiendo. Realmente debería tener un control de acceso por usuario, y sí, eso probablemente significa una base de datos.
    • También pierdes una capacidad de registro significativa cuando no diferencias entre usuarios. Si alguien entra y abusa del sistema, no puede saber quién lo hizo porque todos los inicios de sesión tienen el mismo aspecto. Por supuesto, en el fragmento de código anterior, no tienes ningún registro en absoluto ...
  • No menciona ningún tipo de contraseña de protección de fuerza bruta, sin la cual un atacante externo probablemente pueda descifrar la contraseña, en el peor de los casos, unos pocos días de intentos.

Hay formas correctas de manejar tu escenario, pero todas funcionan de manera diferente a la que estás describiendo.

  1. Restrinja el sitio interno a las direcciones IP de la intranet (red corporativa) y exija que los usuarios externos estén en una VPN.
  2. Delegación de autenticación a su autoridad de inicio de sesión interna. Si tiene un servidor LDAP / Active Directory, puede pasarle la solicitud de autenticación. De hecho, si usa Active Directory e IIS (probablemente no, ya que PHP, pero aún así), esto es tan simple como configurar la aplicación para que requiera "Autenticación de Windows".
  3. Delegue la autenticación a un proveedor externo, si usa uno. Por ejemplo, si su empresa utiliza Google Suite, puede usar el inicio de sesión único (SSO) de Google y verificar que el usuario tenga una dirección de correo electrónico de la empresa. También puede utilizar un proveedor de autenticación externo, como Auth0.
  4. Garantizo que no es necesario que esté alojado en tu dominio público, aunque sin saber por qué piensas, no puedo ofrecer mejores enfoques. Sin embargo, este escenario es exactamente para lo que existen los servidores de intranet, y pueden comunicarse con su servidor web público a través de los canales de back-end (o mediante CORS a través del cliente) si es necesario.

Más en general, el hecho de que preguntes esto indica que probablemente no deberías intentar rodar tu propio sistema de autenticación. Sin saber más sobre el escenario, no puedo decir exactamente cuáles son los riesgos, pero me sorprendería mucho si logras contabilizarlos a todos con un sistema como este. La seguridad es dura; es una idea mucho mejor ir con un sistema probado desarrollado por personas que saben lo que están haciendo.

    
respondido por el CBHacking 07.09.2018 - 23:19
fuente
1

¿Qué / cómo?

Utilice password_hash . Copie el valor de cadena devuelto y péguelo en la fuente. Utilice password_verify para comprobar si la contraseña es correcta.

El algoritmo de

password_hash puede ser PASSWORD_DEFAULT . Incrementar el parámetro de costo de bcrypt es probablemente una buena idea. Argon2 es mejor si los parámetros de costo se ajustan correctamente, pero no sé si los valores predeterminados son buenos o no.

password_verify toma la contraseña suministrada al formulario de inicio de sesión como su primer argumento y una cadena devuelta por password_hash para su segundo.

¿Por qué?

Esto se llama hashing de contraseña. (No cifrado). Los algoritmos de hash de contraseñas son una variación de las funciones criptográficas de hash. Son procesos unidireccionales. No puede recuperar la contraseña del usuario sin primero adivinarla correctamente. Todavía depende del creador de la contraseña elegir una contraseña segura.

En el descifrado de contraseñas fuera de línea, el intruso puede probar las contraseñas candidatas una tras otra, haciendo un trabajo equivalente a lo que hace password_verify , hasta que encuentren una coincidencia. (El cracking sin conexión es cuando alguien roba un hash de contraseña e intenta verificarlo en su propia computadora, evitando las cosas que su servidor podría hacer, como la limitación de velocidad).

Los algoritmos de hash de contraseñas intentan acomodar contraseñas menos seguras forzando a cualquiera que quiera probar una contraseña para que haga más trabajo por cada intento, ya sea legítimo o ilegítimo.

¿Qué más?

Aún debes implementar limitación de velocidad . Tal vez también cierres temporales de cuentas. La lista blanca de direcciones IP también sería una buena idea, pero eso podría causar problemas de uso en algunas situaciones. La lista blanca tampoco es una defensa infalible.

Para realizar bloqueos y límites de velocidad, necesita algún tipo de tienda de lectura / escritura. Las variables de sesión no funcionarían porque un atacante podría comenzar una nueva sesión. Quizás reconsidere sus requerimientos por esta razón. O encuentre otro almacenamiento como un archivo de lectura / escritura fuera de la raíz del documento o el almacén de valores clave.

Para ocultar los hashes de contraseña de alguien con acceso a la fuente PHP, el método más simple de solo lectura que he escuchado es usar SetEnv o fastcgi_param pero eso probablemente cuenta como "archivos conf externos".

Si funcionara, ocultar los hashes haría que fuera más difícil robar los hashes de contraseña. Si no pueden obtener los hashes, no pueden usar el craqueo fuera de línea. Sin embargo no creo que sea de mucha ayuda. Tal vez no estés hackeado todavía. Tal vez alguien hackeó su servidor y tiene mucho más acceso que la capacidad de leer código fuente de PHP. Es posible que alguien solo tenga acceso de lectura a la fuente PHP, pero eso no debería ser probable. Creo que su esfuerzo se gasta mejor evitando errores o configuraciones erróneas para evitar que se produzcan fugas en la fuente PHP en primer lugar.

    
respondido por el Future Security 07.09.2018 - 23:30
fuente
1

Pregunte a un grupo de personas de seguridad cuánta seguridad necesita y ellos le dirán "mucho".

Sí, mantener la contraseña en texto claro mientras lo hace es una mala idea. Mantener la contraseña codificada en tu programa es una mala idea.

Como dice @FutureSecurity, PHP tiene una función útil password_hash que abstrae todas las complejidades de tratar con contraseñas (no solo hash una contraseña, que haces con sha1 () o md5 (), deberías agregue una sal y otra las cosas también ).

Pero, ¿qué quieres aquí? Si es para aprender a ser un mejor programador, lea el uso de password_hash (), pero si solo desea aplicar algún control de acceso seguro, puede ser mejor usar mecanismos de autenticación de Apache .

    
respondido por el symcbean 11.09.2018 - 18:58
fuente

Lea otras preguntas en las etiquetas