Logins seguros

Iniciado por ElInquisidor, 17 Mayo 2016, 18:29 PM

0 Miembros y 1 Visitante están viendo este tema.

ElInquisidor

Alguien sabe como se debe proceder :huh: :huh: :huh: :huh: :huh: :huh: :huh: :huh: :huh: :huh: :huh: para hacer un login super seguro

engel lex

Las claves comparlas en sha y los usernames pasalos a la db en base64 o sha puedes hacer

Código (sql) [Seleccionar]

Select * from usuarios where base64(user)=$u and pass=$p


Y el PHP
Código (php) [Seleccionar]

$u = base64_encode ($user);
$p= sha2($pass );


Esto lo que hara es convertir el usuario a base64 y le dirá a la db que compare con los usuarios convertidos en base64  (esto consume algo de procesador asi que puedes precompilar) y pasa las pass como hashes, esto destruye casi absolutamente  las posibilidades de una inyeccion
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

ElInquisidor

no hay algo mas elaborado  :silbar:


daniela Vega

#4
x

engel lex

daniela Vega Al publicar código debes usar las etiquetas GeSHi

por otro lado tu metodo es una forma facil que te hagan un DoS


primero ya no debes usar en php la extensión mysql, ya que está obsoleta, debes usar mysqli o mysql pdo...

segundo al hacer "SELECT user,pass FROM user", te estás trayendo toda la tabla, si son miles de usuarios te ocupará la ram y tiempo de ejecución se notará facilmente y su varios usuarios simplemente llaman maliciosamente (ni si quiera necesitan enviar datos porque no comprobaste primero) te van a tumbar el site
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

el-brujo

#6
daniela Vega ese código a parte de malo es muy viejo.

Ahora se usa el conector mysqli, no mysql

Ejemplos:

Código (php) [Seleccionar]
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);

$stmt->execute();

$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
   // do something with $row
}



Código (php) [Seleccionar]
<?php
    $mysqli 
= new mysqli("server""username""password""database_name");

    
// TODO - Check that connection was successful.

    
$unsafe_variable $_POST["user-input"];

    
$stmt $mysqli->prepare("INSERT INTO table (column) VALUES (?)");

    
// TODO check that $stmt creation succeeded

    // "s" means the database expects a string
    
$stmt->bind_param("s"$unsafe_variable);

    
$stmt->execute();

    
$stmt->close();

    
$mysqli->close();
?>



Código (php) [Seleccionar]
$name = $_GET['username'];

if ($stmt = $mysqli->prepare("SELECT password FROM tbl_users WHERE name=?")) {

   // Bind a variable to the parameter as a string.
   $stmt->bind_param("s", $name);

   // Execute the statement.
   $stmt->execute();

   // Get the variables from the query.
   $stmt->bind_result($pass);

   // Fetch the data.
   $stmt->fetch();

   // Display the data.
   printf("Password for user %s is %s\n", $name, $pass);

   // Close the prepared statement.
   $stmt->close();

}



Código (php) [Seleccionar]
<?php

/**
 * Check if the 'id' GET variable is set
 * Example - http://localhost/?id=1
 */
if (isset($_GET['id'])){
  
$id $_GET['id'];
  
/**
   * Validate data before it enters the database. In this case, we need to check that
   * the value of the 'id' GET parameter is numeric
   */
   
if ( is_numeric($id) == true){
    try{ 
// Check connection before executing the SQL query 
      /**
       * Setup the connection to the database This is usually called a database handle (dbh)
       */
      
$dbh = new PDO('mysql:host=localhost;dbname=sql_injection_example''dbuser''dbpasswd');
      
      
/**
       * We are going to use PDO::ERRMODE_EXCEPTION, to capture errors and write them to
       * a log file for later inspection instead of printing them to the screen.
       */
      
$dbh->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
      
      
/**
       * Before executing our SQL statement, we need to prepare it by 'binding' parameters.
       * We will bind our validated user input (in this case, it's the value of $id) to our
       * SQL statement before sending it to the database server.
       *
       * This fixes the SQL injection vulnerability.
       */
      
$q "SELECT username 
          FROM users
          WHERE id = :id"
;
      
// Prepare the SQL query
      
$sth $dbh->prepare($q);
      
// Bind parameters to statement variables
      
$sth->bindParam(':id'$id);
      
// Execute statement
      
$sth->execute();
      
// Set fetch mode to FETCH_ASSOC to return an array indexed by column name
      
$sth->setFetchMode(PDO::FETCH_ASSOC);
      
// Fetch result
      
$result $sth->fetchColumn();
      
/**
       * HTML encode our result using htmlentities() to prevent stored XSS and print the
       * result to the page
       */
      
print( htmlentities($result) );
      
      
//Close the connection to the database
      
$dbh null;
    }
    catch(
PDOException $e){
      
/**
       * You can log PDO exceptions to PHP's system logger, using the Operating System's
       * system logging mechanism
       *
       * For more logging options visit http://php.net/manual/en/function.error-log.php
       */
      
error_log('PDOException - ' $e->getMessage(), 0);
      
/**
       * Stop executing, return an 'Internal Server Error' HTTP status code (500),
       * and display an error
       */
      
http_response_code(500);
      die(
'Error establishing connection with database');
    }
   } else{
    
/**
     * If the value of the 'id' GET parameter is not numeric, stop executing, return
     * a 'Bad request' HTTP status code (400), and display an error
     */
    
http_response_code(400);
    die(
'Error processing bad or malformed request');
   }
}


Y se debería usar en las sentencias SQL el parámetro LIMIT 1.

Recuerda deshabilitar  las "emulated prepared statements"

Código (php) [Seleccionar]
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Recuerda que a partir de PHP 5.5.0 la función mysql_real_escape_string ya no existen y se debe usar la función :

mysqli::escape_string

Tienes más ejemplos con SMF 2.1 (BETA) que ya usa bcrypt para cifrar las contraseñas.

http://php.net/manual/es/security.database.sql-injection.php
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

Hashes con salt

Los hashes con salt, son como los hashes de toda la vida pero con unplus de seguridad. En este caso el truco está en la salt que se le agrega. Salt es un número de dígitos aleatorios que se le agrega al hash ya sea al principio o al final. Con lo que los hashes ya no son los normales y por ende no figurarán en una tabla haciendo más dificil  crackearlos. Ya que se deberá probar no solo con cada hash, sino tambien con cada salt y sus combinaciones.

Las funciones de hash más conocidas y utilizadas eran MD5 y SHA-1, pero dado que MD5 y SHA-1 han sido comprometidas, actualmente se recomienda el uso de nuevas funciones como son SHA-2 y Bcrypt.

El hecho de que los hashes sin salt no se combinaran con un valor "único" (salt) para que cada cuenta, hace que el proceso de crackeo sea mucho más rápido ya que requiere menos cálculo.

Gracias al "salt", garantiza que cada hash almacenado es único, incluso si dos usuarios eligen la misma contraseña de acceso, cada uno de hash en una tabla comprometida debe ser crackeada por separado.


La nueva API para codificar contraseñas de PHP 5.5

Internamente la API utiliza la función crypt() y está disponible desde la versión 5.5.0 de PHP. Si utilizas una versión anterior de PHP, siempre que sea igual o superior a 5.3.7, existe una librería con las mismas funcionalidades que la nueva API: github.com/ircmaxell/password_compat.

La función más importante de la nueva API es password_hash(), que codifica la contraseña que le pases con el algoritmo indicado

El primer argumento de la función es la contraseña original sin codificar y el segundo argumento debe ser una de las dos siguientes constantes

- PASSWORD_DEFAULT, codifica la contraseña utilizando el algoritmo bcrypt y el resultado es una cadena de 60 caracteres de longitud, cuyos primeros caracteres son $2y$10$. El algoritmo utilizado y la longitud de la contraseña codificada cambiarán en las próximas versiones de PHP, cuando se añadan algoritmos todavía más seguros. Si guardas las contraseñas en una base de datos, la recomendación es que reserves 255 caracteres para ello y no los 60 que se pueden utilizar actualmente.
- PASSWORD_BCRYPT, a pesar de su nombre, codifica la contraseña utilizando el algoritmo CRYPT_BLOWFISH. Al igual que en el caso anterior, la contraseña codificada ocupa 60 caracteres en total, siendo los primeros caracteres $2y$.

El tiempo empleado en codificar una contraseña se denomina "coste" y se puede configurar mediante el tercer argumento opcional de la función password_hash(). El coste por defecto es 10 (por eso el prefijo de las contraseñas anteriores es $2y$10$) y su valor debe estar comprendido entre 04 y 31.


http://php.net/manual/es/function.password-hash.php

gAb1

En el siguiente articulo se pueden encontrar una serie de pasos a seguir para almacenar las contraseñas de manera segura, es algo avanzado y requiere un mínimo de conocimientos.

Pero creo que es igual o más importante el como se envian:

A mí por ejemplo no me gusta que las contraseñas salgan del cliente en texto plano, por eso las hasheo con javascript. Ya sé que hay tablas, por eso, el hash también se puede saltear, aunque estoy pensando en una una manera segura de conseguir hacer esto (de que no se sepa el salt que uso en el cliente). Cuanto más largo el salt, más cuesta saltear las tablas (yo lo hasheo así ambos, hash y salt, tienen 128 caracteres).

Una vez solucionado el anterior problema, ya nadie conoceria la contraseña del usuario, pero, en caso de robarle el hash podria loguear... Este es el segundo problema que surge a la hora de proteger las contraseñas. Y el primero en caso de no hashear en el cliente. No tengo en cuenta ssl porque esto es un "worst-case scenario"  ;D.

Se aceptan sugerencias  :rolleyes:

hectornunezrivas

Hola buenas noches.
Para hacer un login seguro pues involucra muchas cosas como cifrar passwords y las sesiones por ejemplo. te paso un link el cual te puede ayudar.
http://blackbe.lt/php-secure-sessions/
Saludos