12. Gestión de usuarios con MySQL y PHP

12.1. Uso de SSL

  • Siempre que se introduzcan contraseñas en una página, es altamente recomendable el uso de SSL, que evita ataques de tipo man-in-the-middle
  • Se pueden usar certificados auto-firmados (para pruebas) o certificados firmados por una entidad gestora (Let’s Encrypt, por ejemplo, es gratuito)
  • Si se van a usar proxys, desactivarlos hasta tener SSL funcionando.

12.1.1. Configuración en Apache

  • Pasos para instalar un certificado SSL de Let’s Encrypt (Ubuntu 18.04, requiere poseer un dominio)
    1. sudo a2enmod ssl
    2. sudo a2enmod rewrite
    3. sudo apt-get update
    4. sudo apt-get install software-properties-common
    5. sudo add-apt-repository ppa:certbot/certbot
    6. sudo apt-get update
    7. sudo apt-get install python-certbot-apache
    8. sudo certbot --apache certonly
    9. Para renovar todos los certificados certbot renew. Para actualizar alguno en concreto, certbot --apache certonly
    10. Haz los siguientes ajustes en el virtualhost ssl (si el virtualhost http tiene añadidos, hay que incluirlos en el virtualhost ssl):
      <IfModule mod_ssl.c>
      <VirtualHost *:443>
      ServerName www.ejemplo.rs1.es
      ServerAlias ejemplo.rs1.es
      DocumentRoot /var/www/arbol
      SSLEngine On
      SSLCertificateFile /etc/letsencrypt/live/ejemplo.rs1.es/fullchain.pem
      SSLCertificateKeyFile /etc/letsencrypt/live/ejemplo.rs1.es/privkey.pem
      <FilesMatch ".(cgi/shtml/phtml/php)$">
      SSLOptions +StdEnvVars
      </FilesMatch>
      </VirtualHost>
      </IfModule>
    11. Haz los siguientes ajustes en el virtualhost http para redirigir de HTTP a HTTPS:
      RewriteEngine On
      RewriteCond %{HTTP_HOST} =ejemplo.com [OR]
      RewriteCond %{HTTP_HOST} =www.ejemplo.com
      RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=permanent]
      • OPC:
        RewriteCond %{HTTP_HOST} =85.251.67.151
        RewriteRule ^(.*)$ https://ejemplo.com$1 [L,R=301]
    12. Comprueba si se ha habilitado la web ssl (sudo a2ensite ssl.conf)
    13. Redirige puerto 443 en el router a la IP local del servidor
    14. Reinicia apache (sudo service apache2 restart)
    15. Comprueba si hay que habilitar SSL en el panel de administración de la web, si lo tiene
      • Notas: Si hay que pasar las llaves de un servidor a otro, recuerda que el propietario es root.

12.1.2. Configuración en Nginx

  1. sudo apt-get install python-certbot-nginx
  2. sudo certbot --nginx certonly
  3. En el archivo de configuración de la página:
    server {
       listen 443    ssl;
       server_name   www.ejemplo.rs1.es ejemplo.rs1.es;
       root          /var/www/ejemplo;
       index         index.php index.html;
       location ~ .php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
       }
       ssl_certificate /etc/letsencrypt/live/ejemplo.rs1.es/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/ejemplo.rs1.es/privkey.pem;
       ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
       ssl_ciphers   HIGH:!aNULL:!MD5;
     }
  4. Para redirigir de http a https:
    • return 301 https://$server_name$request_uri;

12.2. Creación de la tabla con los datos de usuario

mysql -p -u bd_usuario
> USE basedatos;
> CREATE TABLE usuarios (user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(100) NOT NULL, pass VARCHAR(255) NOT NULL);

12.3. Creación del formulario de registro / inicio de sesión

<form id="form1" method="post" action="signup.php"  onsubmit="return comprueba_regex('form1');">
    <input type="text" id="username" name="username"    placeholder="Usuario"/><br/>
    <input type="password" id="pass" name="pass"    placeholder="Contraseña"/><br/>
    <button type="submit" id="signup">Añadir usuario</button>
    </form>

12.4. Añadir usuarios

  • En la página a la que se envían los datos del formulario (propiedad ‘action’ del formulario)
 <?php $user = $_POST['username']; $pass = $_POST['pass']; $pass1 = hash('sha512', $pass); $sql_comprueba = "SELECT * FROM tabla WHERE username = '" . htmlspecialchars ( $user, ENT_QUOTES, 'UTF-8' ) . "'"; $result = mysqli_query($link, $sql_comprueba); $extract = mysqli_num_rows($result); if($extract != 0){     echo "<p>El nombre de usuario ya existe</p><br/>";     echo "<a href='/'>Volver</a>"; }else{     $sql = "INSERT INTO tabla     SET username = '" . htmlspecialchars ( $user, ENT_QUOTES, 'UTF-8' ) . "', pass = '$pass1'";     if(mysqli_query($link, $sql)){         echo "<p>El usuario ha sido añadido correctamente</p><br/>";     echo "<a href='/'>Volver</a>";     } else {         echo "ERROR: Could not able to execute $sql. " . mysqli_error($link);     } } mysqli_close($link); ?>
  

12.5. Inicio de sesión

  • En la página a la que se envían los datos del formulario (propiedad ‘action’ del formulario)
    <?php
    $user = $_POST['username2'];
    $pass = $_POST['pass2'];
    $pass1 = hash('sha512', htmlspecialchars ( $pass,   ENT_QUOTES, 'UTF-8' ));
    $sql = "SELECT * FROM tabla WHERE username = '" . htmlspecialchars ( $user, ENT_QUOTES, 'UTF-8' ) . "' AND pass = '" . $pass1 . "'";
    $result = mysqli_query($link, $sql);
    $extract = mysqli_num_rows($result);
    if($extract == 0){
    echo "<p>El usuario y/o la contraseña son incorrectos</p><br/>";
    echo "<a href='/'>Volver</a>";
    }else{
    echo "<p>Inicio correcto</p><br/>";
    echo "<a href='/'>Volver</a>";
    }
    mysqli_close($link);
    ?>

12.6. Creación de un registro de sesiones

  • Es una modificación del anterior código
    (...)
    $log = date('Y-m-j_H:i:s') . " - " . $_SERVER['REMOTE_ADDR'] .
    " - El inicio de sesión del usuario " . $user;
    if($extract == 0){
        $log = $log . " ha fallado";
        (...)
    }else{
        $log = $log . " ha sido un éxito";
        (...)
    }
    $log = $log . "n";
    file_put_contents('./log_'.date("j.n.Y").'.txt', $log, FILE_APPEND);
    (...)

12.7. Más opciones de seguridad

12.7.1. Fail2Ban

  • Introducción
    • Es un programa que evita los ataques por fuerza bruta, al limitar el número de intentos de inicio de sesión por IP.
  • Instalación (en Ubuntu)
    • sudo apt install fail2ban
  • Creación del filtro (ejemplo)
    • sudo vim /etc/fail2ban/filter.d/owncloud.conf
      [Definition]
      failregex={"reqId":".*","level":2,"time":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' (Remote IP: '<HOST>')"}
  • Creación del “jail” (ejemplo)
    • sudo vim /etc/fail2ban/jail.local
      [nextcloud]
      enabled = true
      filter  = nextcloud
      port    = https
      bantime  = 3000
      findtime = 600
      maxretry = 4
      logpath = /var/www/nextcloud/data/nextcloud.log
  • Reiniciar el servicio
    • sudo service fail2ban restart
  • Desbanear una IP
    • sudo fail2ban-client set nextcloud unbanip 1.2.3.4

12.7.2. Autentificación en dos pasos

  • La autentificación en dos pasos permite añadir una capa de seguridad a los inicios de sesión al requerir, además de la contraseña, un código de seis cifras que se envía al móvil del usuario.