Foros del Web » Programando para Internet » PHP »

Seguridad Sesiones PHP + MYSQL

Estas en el tema de Seguridad Sesiones PHP + MYSQL en el foro de PHP en Foros del Web. Buenas tardes a todos! Estoy intentando aumentar la seguridad de mi web, encriptando las sesiones y haciendo comprobaciones en todas mis paginas. Encontre un código ...
  #1 (permalink)  
Antiguo 07/05/2013, 08:10
 
Fecha de Ingreso: septiembre-2012
Ubicación: Palma de Mallorca
Mensajes: 25
Antigüedad: 11 años, 7 meses
Puntos: 1
Pregunta Seguridad Sesiones PHP + MYSQL

Buenas tardes a todos!

Estoy intentando aumentar la seguridad de mi web, encriptando las sesiones y haciendo comprobaciones en todas mis paginas.
Encontre un código en esta misma web muy util:

http://www.forosdelweb.com/f18/aporte-seguridad-basica-php-1011808/#post4265380

Se ve un ejemplo completo de login, comprobacion si es usuario o no y logout.

En principio funciona perfectamente, el problema es cuando lo adapto a mi codigo con Mysql.

Entoces peta todo!

Código PHP:
<?php
require 'db.php';

// Un pequeño agregado para usar en md5()
DEFINE('SALT_MD5''AbC%"$%"');

// Obtener cadena de comprobación
function strMd5($cadena) {
    return 
md5(SALT_MD5 $cadena SALT_MD5);
}
// Ingreso de usuario
function login($userMail,$userPass) {
    
session_regenerate_id(true);

    
$sqlLogin mysql_fetch_assoc(mysql_query("SELECT u_id, u_nombre,u_pass,u_email,u_nivel,u_creditos FROM user WHERE u_email='$userMail' and u_pass = '$userPass'"));

    
$_SESSION = array(
        
'usuario' => array(
            
'id' => $sqlLogin['u_id'],
            
'nombre' => $sqlLogin['u_nombre'],
            
'correo' => $sqlLogin['u_email'],
            
'rol' => $rol,
            
'comprobacion' => strMd5("{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['nombre']}|{$_SESSION['usuario']['correo']}|{$_SERVER['REMOTE_ADDR']}")
        )
    );
    
// Creamos cookie 'usuario' con id y cadena de comprobación
    // Expira en un mes y está disponible en la raiz del sitio y todas las subcarpetas
    
setcookie('usuario'"{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['comprobacion']}"time() + (86400 30), '/');
    
print_r($_SESSION['usuario']);
    
// Redirigimos a página de usuario
    
header('Location: otro.php');
    exit;
}
// Finalizar sesión
function logout() {
    
// Creamos una nueva id de sesión y eliminamos la anterior (true)
    
session_regenerate_id(true);
echo 
'sañor';
    
// Eliminamos información de sesión
    
$_SESSION = array();

    
// Borramos info de cookie
    
setcookie('usuario''sin sesión'time() + 3600'/');

    
// Redirigimos a página principal
    
header('Location: index2.php');
    exit;
}
// Comprobar si es una sesión válida
// Devuelve verdadero sólo si el usuario inició sesión y la cadena de comprobación es correcta
// Si el usuario cambia de IP, entonces finalizará su sesión
function esUsuario() {
    
// Si no existe la variable de sesión
    
if( ! isset($_SESSION['usuario'])) {
        
// Entonces buscamos en cookie
        
$cookie = (isset($_COOKIE['usuario'])) ? $_COOKIE['usuario'] : 'sin sesión';
        if(
$cookie != 'sin sesión' && $cookie != '') {
            
// Separamos ud y cadena de comprobación
            
$tmp explode('|'$cookie);

            
// Sólo será válida si son dos elementos
            
if(count($tmp) == 2) {
                
$id = (int) $tmp[0];
                
$comp mysql_fetch_assoc(mysql_query("SELECT u_id, u_nombre,u_pass,u_email,u_nivel,u_creditos FROM user WHERE u_id='$id'"));
//                $sql = "SELECT id, nombre, correo, rol FROM usuarios WHERE id = $id";
                // Leemos la consulta con nuestra librería preferida

                // Si los datos son válidos, creamos variables de sesión
                
$_SESSION['usuario'] = array(
                    
'id' => $comp['u_id'],
                    
'nombre' =>$comp['u_nombre'],
                    
'correo' => $comp['u_email'],
                    
'rol' => "jodido",
                    
'comprobacion' => $tmp[1// La cadena obtenida de cookie
                
);
            }
        }
    }
    if(isset(
$_SESSION['usuario'])) {
        
$cadena "{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['nombre']}|{$_SESSION['usuario']['correo']}|{$_SERVER['REMOTE_ADDR']}";
        if(
strMd5($cadena) == $_SESSION['usuario']['comprobacion']) {
            
// Sesión válida, renovamos cookie para mantenerlo conectado
            
setcookie('usuario'"{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['comprobacion']}"time() + (86400 30), '/');

            return 
true;
        }
        
// Sesión no válida, posiblemente es un ataque
        // Cerramos sesión
        
echo 'Sesion no valida';
        echo 
'<br/>';
        
print_r($_SESSION['usuario']);
         echo 
'<br/>';
        
print_r(strMd5($cadena));
        
logout();
    }
    
// No hay sesión válida, nos aseguramos de que la cookie siga sin datos
    
setcookie('usuario''sin sesión'time() + 3600'/');
    return 
false;
}
?>
Esto es lo que tengo hasta ahora... el problema, creo, esta cuando comprueba las dos cadenas encriptadas, ya que nunca dan igual!

Espero haberme explicado, y que alguien vea el fallo! un saludo a todos y gracias de antemano
  #2 (permalink)  
Antiguo 07/05/2013, 15:24
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Seguridad Sesiones PHP + MYSQL

Cómo estás haciendo el login?

Lo primero que veo mal es que tienes en una misma línea mysql_fetch_assoc() y mysql_query(), debiendo ser más o menos así:

Código PHP:
Ver original
  1. $result = mysql_query(/* aquí la consulta */);
  2. if(mysql_num_rows() == 1) {
  3.     // Ok, el usuario existe
  4.     $sqlLogin = mysql_fetch_assoc($result);
  5.     // Aquí creas variables de sesión necesarias y cookie
  6. } else {
  7.     die('Nombre de usuario y/o contraseña inválidos');
  8. }
__________________
- León, Guanajuato
- GV-Foto
  #3 (permalink)  
Antiguo 08/05/2013, 13:22
 
Fecha de Ingreso: septiembre-2012
Ubicación: Palma de Mallorca
Mensajes: 25
Antigüedad: 11 años, 7 meses
Puntos: 1
Respuesta: Seguridad Sesiones PHP + MYSQL

Cita:
Iniciado por Triby Ver Mensaje
Cómo estás haciendo el login?

Lo primero que veo mal es que tienes en una misma línea mysql_fetch_assoc() y mysql_query(), debiendo ser más o menos así:

Código PHP:
Ver original
  1. $result = mysql_query(/* aquí la consulta */);
  2. if(mysql_num_rows() == 1) {
  3.     // Ok, el usuario existe
  4.     $sqlLogin = mysql_fetch_assoc($result);
  5.     // Aquí creas variables de sesión necesarias y cookie
  6. } else {
  7.     die('Nombre de usuario y/o contraseña inválidos');
  8. }
Buenas Triby!
Justamente el código que encontre era tuyo...gran aporte, lástima que no sepa adaptarlo de momento.


Código PHP:
function login($userMail,$userPass) {
    
session_regenerate_id(true);

    
$result mysql_query("SELECT u_id, u_nombre,u_pass,u_email,u_nivel,u_creditos FROM user WHERE u_email='$userMail' and u_pass = '$userPass'");
  
if(
mysql_num_rows() == 1) {
    
$sqlLogin mysql_fetch_assoc($result);
    
//Creamos Sesiones
    
$_SESSION = array(
        
'usuario' => array(
            
'id' => $sqlLogin['u_id'],
            
'nombre' => $sqlLogin['u_nombre'],
            
'correo' => $sqlLogin['u_email'],
            
'rol' => $rol,
            
'comprobacion' => strMd5("{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['nombre']}|{$_SESSION['usuario']['correo']}|{$_SERVER['REMOTE_ADDR']}")
        )
    );
    
// Creamos cookie 'usuario' con id y cadena de comprobación
    
setcookie('usuario'"{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['comprobacion']}"time() + (86400 30), '/');

}else{
    echo 
'No existe el usuario';
}


He modificado el Login tal como me comentaste, y el resto esta igual. Me crea la sesion y la cookie y me la encripta, pero cuando el header me redirecciona pierdo la sesion. No acabo de entender la primera parte de la funcion esUsuario(); por eso me debe petar....
Edito: Incluyo en ese fichero un acceso a la BD donde también inicio la sesiín, y que esta incluido en todos los archivos

Un saludo y gracias por compartir!

Última edición por jrBarcelo; 08/05/2013 a las 13:31
  #4 (permalink)  
Antiguo 08/05/2013, 13:33
 
Fecha de Ingreso: abril-2005
Ubicación: Piura - Perú
Mensajes: 189
Antigüedad: 19 años
Puntos: 0
Respuesta: Seguridad Sesiones PHP + MYSQL

te recomiendo usar cookies con el contenido en MD5, ahora, has revisado si el session_start(); esta al inicio de la pagina a donde te lleva el header??

Link de refencia : http://php.net/manual/es/function.session-start.php
  #5 (permalink)  
Antiguo 08/05/2013, 13:37
 
Fecha de Ingreso: septiembre-2012
Ubicación: Palma de Mallorca
Mensajes: 25
Antigüedad: 11 años, 7 meses
Puntos: 1
Respuesta: Seguridad Sesiones PHP + MYSQL

Cita:
Iniciado por KenMasters Ver Mensaje
te recomiendo usar cookies con el contenido en MD5, ahora, has revisado si el session_start(); esta al inicio de la pagina a donde te lleva el header??

Link de refencia : [url]http://php.net/manual/es/function.session-start.php[/url]
Buenas!

Si,esta incluido... por ahí no va la cosa. Si envio dos veces el formulario de Login, y creo dos veces las variables de sesion y la cookie, quitando el header,y paso a otra sección de la web, entonces si que me mantiene la sesion.

Es como si no se actualizar la sesión cuando hago login... nose,ando un poco perdido!

Gracias por contestar
  #6 (permalink)  
Antiguo 08/05/2013, 20:01
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 8 meses
Puntos: 2237
Respuesta: Seguridad Sesiones PHP + MYSQL

De momento, un error mío, mysql_num_rows() requiere un parámetro, en este caso, $result... pequeño detalle que se me (nos) pasó.

La función esUsuario() lo único que hace es verificar si el usuario actual tiene sesión iniciada o es un invitado.

Sugerencia, después de login redirige a una página donde sólo tengas:
Código PHP:
Ver original
  1. <?php
  2. var_dump($_SESSION, $_COOKIE);

Con eso vas a ver lo que hay en sesiones y en cookies, si todo va bien, entonces llamas a la función esUsuario() y vuelves a usar var_dump() para ver si hay cambios, si es el caso, entonces en esa función algo hay mal... como comentaba en ese tema, son ejemplos y no todos los probé, pero podemos hacerlo funcionar.
__________________
- León, Guanajuato
- GV-Foto
  #7 (permalink)  
Antiguo 09/05/2013, 02:12
 
Fecha de Ingreso: septiembre-2012
Ubicación: Palma de Mallorca
Mensajes: 25
Antigüedad: 11 años, 7 meses
Puntos: 1
Respuesta: Seguridad Sesiones PHP + MYSQL

Cita:
Iniciado por Triby Ver Mensaje
De momento, un error mío, mysql_num_rows() requiere un parámetro, en este caso, $result... pequeño detalle que se me (nos) pasó.

La función esUsuario() lo único que hace es verificar si el usuario actual tiene sesión iniciada o es un invitado.

Sugerencia, después de login redirige a una página donde sólo tengas:
Código PHP:
Ver original
  1. <?php
  2. var_dump($_SESSION, $_COOKIE);

Con eso vas a ver lo que hay en sesiones y en cookies, si todo va bien, entonces llamas a la función esUsuario() y vuelves a usar var_dump() para ver si hay cambios, si es el caso, entonces en esa función algo hay mal... como comentaba en ese tema, son ejemplos y no todos los probé, pero podemos hacerlo funcionar.


Buenos días! Me ha servido de ayuda esto que me comentaste, y creo que he encontrado el fallo en la función esUsuario(); Corrígeme si me equivoco,me explico...
Código PHP:
function esUsuario() {
    
    if( ! isset(
$_SESSION['usuario'])) {
        
//Aqui las operaciones si no existe la sesion
    
}
    
    if(isset(
$_SESSION['usuario'])) {
        
$cadena "{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['nombre']}|{$_SESSION['usuario']['correo']}|{$_SERVER['REMOTE_ADDR']}";
        if(
strMd5($cadena) == $_SESSION['usuario']['comprobacion']) {
            
// Sesión válida, renovamos cookie para mantenerlo conectado
            
setcookie('usuario'"{$_SESSION['usuario']['id']}|{$_SESSION['usuario']['comprobacion']}"time() + (86400 30), '/');

            return 
true;
        }
        
// Sesión no válida, posiblemente es un ataque
        // Cerramos sesión
     
        
logout();//Si existe la sesion, y aunque la cadena y la sesion de comprobacion sean iguales, siempre haremos logout y por tanto la cookie estara en modo sin sesion,¿no?
    
}
    
// No hay sesión válida, nos aseguramos de que la cookie siga sin datos
    
setcookie('usuario''sin sesión'time() + 3600'/');//Aqui al final de la comprobación cambiaremos la cookie tambien, si o si, exista o no la sesion.
    
return false;

Al final de la función ,se ve que hacemos logout() y modificamos la cookie, pero estas operaciones no están sujetas a ninguna condición, por tanto siempre se realizaran cada vez que llamemos al script. ¿Voy bien?.

Por tanto modificando esta parte, y poniéndolo donde toca,que es si la cadena y la sesión no son iguales, funciona perfectamente y se mantiene la sesión.
Yo lo que haría, es poner un else donde esta la comparación de la cadena y la sesión comprobación, y poner que si no es igual, haga logout y cambie la cookie.
Quizás este diciendo una tontería.... no soy un experto.

Por otra parte, lo que no estoy seguro es si esta parte funciona bien. Que es el caso en que la session no exista.
Código PHP:
    if( ! isset($_SESSION['usuario'])) {
        
// Entonces buscamos en cookie
        
$cookie = (isset($_COOKIE['usuario'])) ? $_COOKIE['usuario'] : 'sin sesión';
        if(
$cookie != 'sin sesión' && $cookie != '') {
            
// Separamos ud y cadena de comprobación
            
$tmp explode('|'$cookie);
            
// Sólo será válida si son dos elementos
            
if(count($tmp) == 2) {
                
$id = (int) $tmp[0];
                
$result2 mysql_query("SELECT u_id, u_nombre,u_pass,u_email,u_nivel,u_creditos FROM user WHERE u_id='$id'");
                
$comp mysql_fetch_assoc($result2);

                
// Si los datos son válidos, creamos variables de sesión
                
$_SESSION['usuario'] = array(
                    
'id' => $comp['u_id'],
                    
'nombre' =>$comp['u_nombre'],
                    
'correo' => $comp['u_email'],
                    
'rol' => $comp['u_nivel'],
                    
'comprobacion' => $tmp[1// La cadena obtenida de cookie
                
);
                
            }
        }
    } 
Un saludo! y espero explicarme con claridad...a ver si conseguimos que funcione, ya que es un aporte muy interesante.

Etiquetas: encriptacion, sesiones
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:19.