Programación

Contraseñas seguras en PHP

Guardar las contraseñas de forma segura en base de datos es uno de los procesos más habituales y más importante de cualquier aplicación con usuarios. En PHP es muy sencillo hacerlo, pero antes vamos a explicar cuales son los problemas y las soluciones para generar y guardar contraseñas seguras.

Lo primero y más importante es que nunca debemos guardar en plano las contraseñas en la base de datos. El motivo es que si nuestra base de datos se ve comprometida el nombre de usuario y la contraseña puede ser usado en otras webs ya que la mayoría de la gente los reutiliza. Que levante la mano quien no tenga la misma contraseña en decenas de webs.

Entonces, ¿cómo las guardamos?. Podríamos hacerlo utilizando alguno de los algoritmos de hash más comunes como son md5 o sha1 pero por una parte estos algoritmos llevan rotos desde hace años y por otra se podrían utilizan tablas arcoíris (rainbow tables) que no son ni más ni menos que tablas de contraseñas con el hash ya generado de forma que es mucho más sencillo realizar un ataque de fuerza bruta.

Para evitar este tipo de ataques utilizaremos Salt. Pero ¿qué es Salt? Esta técnica consiste en añadir una cadena aleatoria a la contraseña antes de que se utilice para generar el hash. Pongamos un ejemplo sencillo para que se entienda, digamos que la contraseña es la palabra “hola”, lo que vamos a hacer es generar una cadena aleatoria que deberemos guardar en base de datos para poder regenerar el hash de nuevo. Ahora lo que hacemos es por ejemplo concatenar la contraseña con la cadena aleatoria y sobre el resultado de la concatenación generamos el hash. Vendría a ser algo así:

hash(“hola” . “A%$bcJeL”)

La función hash podría ser cualquier función hash segura, el resultado de la cual es lo que guardaremos en base de datos como contraseña y como ya habíamos mencionado también guardaremos el Salt “A%$bcJeL” en el ejemplo para en algún momento poder regenerar el hash y así poder comprobar la contraseña. Para comprobarla lo que haríamos es recuperar el hash y el Salt de base de datos, regenerar el hash con la contraseña que introduzca el usuario en el formulario correspondiente y comparar. Sería algo así:

hash($campoFormulario . $saltDeBaseDeDatos) == $contrasenyaDeBaseDeDatos

Ahora la tabla arcoíris ya no sirve porque los hashes resultantes al tener Salt serán completamente diferentes.

Una vez hemos entendido todo esto ¿cual es la forma correcta de hacerlo en PHP? Pues usar las funciones password_hash y password_verify. La primera genera un hash con Salt de forma automática, nosotros lo único que tenemos que darle es la contraseña en plano y el algoritmo seguro a utilizar para generar el hash. Actualmente se recomienda el algoritmo CRYPT_BLOWFISH pero si le indicamos PASSWORD_DEFAULT como algoritmo entonces la función utilizará el aceptado como más seguro en ese momento de forma que si sale uno mejor será ese el que se empiece a utilizar.

password_hash ( string $password , integer $algo [, array $options ] ) : string

En el ejemplo sería:

password_hash(“hola”, PASSWORD_BCRYPT)

Esto nos generar un hash con este formato:


Como veis tenemos todo lo necesario en un único hash. El tipo de algoritmo que en nuestro caso es CRYPT_BLOWFISH, las opciones del algoritmo si las hubiera, el Salt y el hash de la contraseña. Ahora tan solo necesitamos guardar este hash completo en la base de datos en lugar del hash y el Salt por separado.

Si queremos comprobar la contraseña usaremos la función password_verify a la que tan solo tendríamos que pasarle por un lado la contraseña y por otro el hash completo ya que ahí tiene todos los datos necesarios para la comprobación.

password_verify ( string $password , string $hash ) : bool

Esta función internamente hace algo parecido a lo que hacíamos nosotros en el ejemplo de comprobación con Salt devolviéndonos al final verdadero o falso dependiendo de si la contraseña coincide o no.

Con todo esto ya sabéis como generar un hash seguro y como comprobar la validez de vuestras contraseñas a partir del hash. Pero si tienes cualquier duda déjamela en un comentario.

Nos vemos.

Emular terminal desde PHP en Servidores Virtuales Gestionados (caso de Comvive)

Desde que trabajo en Pórtico Legal quería empezar a usar el sistema de control de versiones (yo siempre lo uso y aquí no tenían nada, una locura) y poder usarlo para los despliegues en preproducción y producción como solución intermedia hasta que tengamos algo más avanzado. Hasta la fecha se estaban haciendo mediante ftp con todos los problemas que eso supone, entre ellos los siguientes y sus posibles soluciones:

  • Mientras se ha subido un archivo y se está subiendo otro que depende de este la web se puede romper, lo más probable es que ocurra. Esto no se solventa completamente usando git sobre un único servidor pero se minimiza muchísimo.
  • Nunca se sabe que versión está en producción. En algunos momento se habían subido archivos por diferentes personas y una no sabía lo que había subido la otra.
  • Si se toca algo en el servidor un simple “git status” te lo va a chivar, y un simple “git checkout …” te va a solucionar la papeleta.
  • Se va a poder desplegar nuevas versiones simplemente etiquetando y haciendo un “git checkout tag

 

Aquí el problema venía por parte del hosting de comvive que al ser un VPS gestionado no te dan cuenta de shell. Para solucionarlo al final utilicé un pequeño script php que ejecutaba la orden que le pasas como parámetro:

<?php

$command = $_GET[“command”];

$res = execute($command, __DIR__ . ‘/..’);
echo “<pre>”;
echo “\nCódigo de salida: ” . $res[‘code’];
echo “\n” . $res[‘out’];
echo “\nSalida de error:\n” . $res[‘err’];
echo “</pre>”;

function execute($cmd, $workdir = null) {
if (is_null($workdir)) {
$workdir = __DIR__;
}

$descriptorspec = array(
0 => array(“pipe”, “r”), // stdin
1 => array(“pipe”, “w”), // stdout
2 => array(“pipe”, “w”), // stderr
);

$process = proc_open($cmd, $descriptorspec, $pipes, $workdir, null);

$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);

$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);

return [
‘code’ => proc_close($process),
‘out’ => trim($stdout),
‘err’ => trim($stderr),
];
}

 

La etiqueta pre la utilizo para que la salida se vea bien si la llamamos desde un navegador. Pues bien, una vez subido podemos ejecutar cualquier orden como:

https://dominio/path/script.php?command=orden

Pero como estarás pensando esto no es seguro. Lo que hice yo es meterlo en un directorio y en este meter un .htaccess para que sólo yo tuviera acceso.

Al final lo único que quería era poder usar git, así que me creé un shell script con wget para llamar a esta url. El script es tal que así:

#!/bin/bash

domain=””

command=”wget -qO – \”http://$domain/commands/command.php?command=git $*\” | sed ‘1d’ | sed ‘\$d'”
echo “Dominio: $domain”
echo “Parámetros: $*”
eval $command

 

Ahora sólo hay que darle permisos de escritura y en mi caso lo he llamado rgit y lo he puesto en el path por comodidad. Esta sería una salida de la orden “rgit status -s“, en este caso un status limpio:

Dominio: www.dominio.com
Parámetros: status -s
Código de salida: 0
Salida de error:

Lo suyo es que el directorio .git con todo el ínidice esté fuera del htdocs del servidor, para ello se puede usar el parámetro –work-tree de git. Si por algún motivo no puede estar fuera podéis utilizar de nuevo un .htaccess para que nadie pueda entrar:

 

deny from all

 

Y con esto he conseguido un rodeo para poder usar una “shell” remota a través de un script PHP. Espero que os sea de ayuda.

 

 

 

La experiencia de desarrollar una App Android en mi tiempo libre

Después de volver de Ecuador en donde estuve trabajando intensamente en un proyecto que me absorbía casi todo el tiempo decidí tomarme un descanso. En ese tiempo pensé en empezar a aprender a desarrollar apps en Android así que me puse a hojear la documentación oficial respecto al diseño y posteriormente empecé a hacer los ejemplitos que había en la documentación técnica. Entonces me dije, ¿por qué no intentas poner en práctica todo lo que vayas aprendiendo en una aplicación que tenga una utilidad real?, y así es como nació Peak Hour.

La primera versión era realmente sencilla pero me sirvió por un lado para aprender los conceptos básicos de Android (Activities, ciclo de vida de las mismas, tantear el IDE que por entonces decidí empezar con Eclipse aunque poco después migré a Android Studio, notificaciones, etc) y por otro tantear el mercado de apps y concretamente la de gestión de Pico y Placa y transporte en general. Estuve jugando con el código un par de meses o tres y para principios de 2015 ya tenía algo que más o menos funcionaba, el problema era que desde que había empezado a trabajar en Planeta Huerto no me quedaba mucho tiempo libre por lo que no fue hasta febrero de 2015 que presenté la app a mis compañeros de Ecuador.

La primera sensación fue decepcionante, a pesar que cuando estuve en Ecuador era muy cotidiano preguntarse entre los compañeros a quién le tocaba Pico y Placa, cuando se la envié a la gente de allí casi nadie la instaló, creo que no les parecía muy útil y eso me hizo replantearme si valía la pena seguir mejorándola. Después de este chasco la tuve medio abandonada durante unos cuantos meses, 5 o 6, en los que sólo hice un par de arreglos y poco más. En esos meses aproveché para hacer un par de cursos MOOC que me ayudaron mucho a entender como está diseñado Android, aprender muchísimo sobre todo de los patrones de diseño que utiliza el sistema, y detectar los problemas que tenía mi app y ver los errores que había cometido durante mi primer abordaje. Ahí es cuando dije, vamos a hacerlo un poco mejor y así también afianzas las cosas que has aprendido en los cursos. También me planteé que si quiero que la app sea utilizada masivamente tiene que ser más flexible y soportar las reglas de más ciudades a parte de Quito y así es como surgieró la versión 0.2 en las que se añadió el soporte multi-vehículo y la versión 0.3 en la que rediseñé completamente el manejo de reglas para que fuera muy sencillo añadir nuevas ciudades.

Estos dos cambios han resultado ser fundamentales, a partir de ese momento empezamos a crecer horizontalmente o lo que es lo mismo, se empezó a utilizar la aplicación en muchos otros sitios como Colombia, Brasil, Bolivia o Costa Rica, pero sobre todo en Colombia que es actualmente el mercado principal de la app. Es muy gratificante pensar que algo que tu has creado le está siendo útil a casi 300 personas, y eso es lo que te impulsa a seguir adelante. Ya os digo yo que por el dinero no es, de momento la app da para tomarse un poleo al mes y poco más, pero saber que toda esa gente no olvida su Pico y Placa y que seguramente se ha salvado de alguna multa gracias a la app, la verdad es que te alegra el día.

 

¿Y qué pasará con la app en el futuro?, pues de momento tengo planificados un par de cambios que ya tengo medio implementados y dependiendo de como vaya la cosa y si tengo tiempo hay muchas ideas en una libreta que parece que va siendo hora de ir sacándolas.

 

Ya os iré contando.