Autenticación de usuarios y sesiones en PHP

Continuando con la pequeña serie de posts que intentan mostrar algunas fallas comunes que hacemos los aficionados a PHP, e incluso los que se dedican profesionalmente a desarrollar aplicaciones con este lenguaje, esta vez tocaremos el tema de sesiones.

user.php, necesita de la clase ezSQL, puedes saber mas sobre esta clase en este artículo.

php:

<?php

class User {
        var $id;
        var $name;
        var $email;
       
        function Authenticate($user, $password) {
                global $db, $site_key;

                $user = $db->get_row (
                        'SELECT id, name, email, password
                                FROM users
                                WHERE username = \''
. $db->escape($user) . '\'');
               
                if ( $user && $user->password == md5( $site_key . $password ) ) {                     
                        $this->id = $user->id;
                        $this->name = $user->name;
                        $this->email = $user->email;
                        return true;
                }
                return false;
        }
}

?>
php:
// login.php
<?php

include dirname(__FILE__) . '/db.php'; # genera una instancia de la clase ezSQL
include dirname(__FILE__) . '/user.php';

/*
if ( ! empty( $_SESSION['user'] ) ) {
        header( 'Location: /admin' );
        exit();
}
*/

if ( ! empty( $_POST['user'] ) && ! empty( $_POST['password'] ) ) {     
        $user = new User();
        if ( $user->Authenticate( $_POST['user'], $_POST['password'] ) === true ) {
                $_SESSION['user'] = $user;
               
                header( 'Location: /admin' );
                exit();
        }
}

?>

¿Qué problema existe en el código mostrado? -no es un error de sintáxis :-D

Nota: si eres testigo de otros errores :-) y quieres compartir esa información, no dudes en contactarnos (describe el problema, una posible solucion, si ya lo publicaste en tu blog, envíanos el link para comentar el problema y citar tu post)

16 thoughts on “Autenticación de usuarios y sesiones en PHP”

  1. hola alguien me podria decir como le hago para que una vez que desplegue un reporte en php de una base de datos oracle pueda pasar esa tabla(reporte) a una pagina html?
    ojala me puedan ayudar o decirme en donde puedo encontrar algo parecido
    gracias

  2. Estoy dudando del problema. Pero quizá sería más correcto que a la claúsula where de la consulta se le agregue un AND y se compare directamente también password. Recien ahí evaluamos sí $user no quedó vacío y se devuelve el true.

    Cual es la respuesta ?

  3. Tienes razón, se ahorrarían más recursos al hacer eso.

    Comentaré la solución el miércoles, por si no le "dan al clavo" en los comentarios :).

  4. hmm puess la verdad es q me he quedado mirando el código como 5 o 10 minutos con cara de besugo pero supongo que te refieres a que no cambia la entrada de datos del nombre de usuario ni la contraseña..
    La verdad es q no he leído la documentación de ezSQL pero supongo q si pones caracteres comodín el sistema lo daría por valido. vamos que el error es de inyección sql.. si ponemos % en un usuario y password entrara sin mas, al igual q podríamos modificar los datos del sistema si en vez de poner:
    %
    ponemos:
    ';INSERT INTO users (id, name, email, password) VALUES ('','ADMIN','XXXX'); SELECT id, name, email, password FROM users WHERE username = '

    A parte otro posible problema podria ser pasar las variables por el post ya que de esa manera se corre mas riesgo de que se pueda hacer fuerza bruta. se tendria q verificar que la informacion biene de una web de dentro del servidor, y si se es ya hiperparanoico traerla encriptada desde el usuario con un javascript.

    A alguien se le ocurre algo mas :-S

  5. Hola Antares,

    No pasa nada si se pones el comodín % en el usuario o password, puesto que en la consulta no se usa LIKE. Tampoco sucedería nada con la segunda cadena que pusiste, puesto que $db->escape llama internamente a mysql_real_escape_string.

    Sobre los ataques con fuerza bruta y captura de información, son posibles problemas, pero existe otro de mayor envergadura :).

  6. A ver, otra que se me ocurre es que el problema este por acá:
    if ( ! empty( $_SESSION['user'] ) ) {
    header( 'Location: /admin' );
    exit();
    }

    Igual no me queda muy claro como se explotaría pero $_SESSION['user'] podría estar sucio por alguna razón y aplicar la redirección. De todas maneras dentro de /admin no tendría que haber ninguna protección, cosa rara si se está usando autentificación por sesiones.

    Pero bue capaz se me está pasando otra cosa más peligrosa.

    Adios.

  7. El código mostrado sufre de un tipo de ataque denominado Session Fixation (no sé como traducirlo :D), en el cuál un usuario puede capturar el ID de la sesión o asignar un ID de sesión de otro usuario, haciendo que los datos de esa sesión sean compartidos entre ambos.

    En un siguiente post explicaré con un poco más de detalle y un ejemplo práctico de este tipo de ataques.

  8. No se de qué manera ese código es vulnerable a "Session Fixation". Ese código no acepta el código de sesión pasado por parámetro. ¿De qué manera puede un usuario fijar tu sesión entonces?

    No lo tengo claro.

  9. Tienes razón, el código parece ser que no es vulnerable a Session Fixation, sin embargo, si se elimina la primera condición si lo sería, puesto que el código mostrado en ningún momento regenera el ID de la sesión.

    Saludos
    PS. Disculpa por la demora en responder

  10. Tengo una aplicación que usa smarty, en ellla uso sesiones para la autenticacion de usuarios, me han echo cambiar las tpl para cambiar el diseño.

    Con las antiguas TPLs funciona muy bien, pero con las nuevas no carga la sesión usando firefox pero usando IE funciona muy bien.

    La pregunta en cuestion es: ¿firefox modifica de alguna forma las sesiones?

    Desde luego, las sesiones se han echo para no ser modificadas desde el lado del cliente, pero sospecho que estas podrían cargarse o no cargarse según alguna cabecera que mande firefox.

    He comparado el html que manda la aplicación con una y otra tpl, buscando en el código que mandan los formularios y la cabecera html.

    Podrían guisas ustedes tener una idea mas clara de que podría ser.

  11. hola, creo que lo mio es bien sencillo. Necesito dos campos en mi fomulario: uno "cedula" y otro "password", si el usuario escribe bien su cedula y la clave que le pide el formulario entonces le devuelve ciertos registros de la tabla en el servidor con su info. Gracias desde ya.

  12. creo que es vulnerable a sql inyeccion ya que a los valores que te da el usuario no le quitas las "" o ' o / o /*

  13. tengo un problema y es que cuando utilizo una clase para consultar mi BDD y luego utilizo header para direccionar a otra pagina me despliega un error

  14. creo que el problema es que se están usando variables de sesión y nunca se ha iniciado una, es decir, no existe un "session_start();"

  15. hola a todos he estado probando los ejemplo pero no me salen alguien por ahi tendra un ejemplito o este ejemplo y me lo podria mandar a mi correo sdarknot@gmail.com en verdad me interesa mucho aprender este estilo de programar bueno desde ya gracias xD .....

Comments are closed.