Pregunta Seguridad con sesiones de PHP


Sé que esto se ha preguntado miles de millones de veces, pero estoy super paranoico / OCD sobre la seguridad de mi codificación. Estoy trabajando en un pequeño proyecto. Los datos de la sesión solo contendrán:

identidad de usuario  1
user_name Mi nombre de usuario
conectado cierto
csrf_token 87cc51ee94178df79cccce2aebc45d53

Aquí está mi código. Lo es seguro suficiente para usar en un pequeño CMS?

session_start();

ini_set('session.cookie_httponly', 'On');
ini_set('session.cookie_secure', 'On');
ini_set('session.use_cookies', 'On');
ini_set('session.use_only_cookies', 'On');

$rand = rand(1, 10);

if ($rand != 1 || $rand != 3 || $rand != 5)
    session_regenerate_id();

$user_ip = md5($_SERVER['REMOTE_ADDR']);
$user_agent = md5($_SERVER['HTTP_USER_AGENT']);

if (isset($_SESSION['user_ip'], $_SESSION['user_agent'])) {
    $session_user_ip = $_SESSION['user_ip'];
    $session_user_agent = $_SESSION['user_agent'];

    if ($session_user_ip != $user_ip || $session_user_agent != $user_agent) {
        unset($_SESSION);
        session_destroy();

        die('Error');
    }
} else {
    $_SESSION['user_ip'] = $user_ip;
    $_SESSION['user_agent'] = $user_agent;
}

Luego para llamar a las sesiones:

$_SESSION['user_id'] = 1;
$_SESSION['user_name'] = 'MyUsername'; // etc.

Información extra
Usaré los datos de la sesión para verificar si el usuario tiene permisos para hacer algo. Ejemplo: if ( user_has_perm( $_SESSION['user_id'] ) )

Gracias por su ayuda con anticipación.


8
2018-01-14 14:39


origen


Respuestas:


Los riesgos de seguridad de la sesión provienen de tres posibilidades diferentes:

  • Predicción
  • Capturar
  • Fijación

La predicción significaría que alguien que no es el usuario para quien se creó la sesión adivinó su ID de sesión. Las posibilidades de que eso ocurra son casi 0, aunque crecen a medida que más usuarios usan el sitio simultáneamente.

Con su código, usted haría ese riesgo aún más bajo porque solo funcionaría si el atacante compartiera el agente de usuario y la ip de la sesión pronosticada. Pero la diferencia es trivial en este caso.

La fijación significaría que un atacante puede crear una sesión y luego forzar a otro usuario a usar su sesión. En este caso, dependería: si el atacante sabe que lo está haciendo y falsifican el agente de usuario y la IP del cliente, podrían fijar la sesión. O si comparten ip y agente de usuario.

Y finalmente tenemos secuestro de sesión, probablemente el método más común de los tres. En este caso, un atacante tendría acceso de algún modo al ID de la sesión de un usuario con sesión iniciada válida y luego lo usaría para iniciar sesión en su cuenta. Al igual que con el método anterior, esto solo funcionaría para ellos si saben que está comprobando el IP y el agente de usuario, y falsificó los mismos que el usuario. La técnica que estás usando no es única, y algunos atacantes podrían falsificarla por si acaso.


Dicho esto, ¿es seguro?  y no

Si estás obsesionado con la seguridad, la respuesta es siempre la misma: Use SSL

A menos que su código sea de código abierto, casi cualquier cosa que haga que cambie el comportamiento de las sesiones de php será lo suficientemente seguro.

La única excepción a eso serían los sitios realmente populares que atraerán la atención de los piratas informáticos.

Hay muy buena documentación disponible sobre este tema:


12
2018-01-14 14:59



No soy un experto en seguridad. Sin embargo, dudo humildemente de que sus medidas de seguridad traerán sustancial beneficios.

Si hay alguien que puede robar la identificación de la sesión de tus usuarios, por ejemplo, escuchando a escondidas una red inalámbrica no encriptada, apuesto a que puede robar también el nombre de usuario y la contraseña que tus usuarios envían a tu servidor cuando se autentican. Una vez que tiene las credenciales de acceso, el atacante puede iniciar sesión el día después o una semana después, y tendrá su sesión "segura" y 100% válida para jugar.

Creo que no hay seguridad de sesión sin la seguridad del canal. Si tu usar SSL, se asegura de que la ID de la sesión se envíe solo a través de las cookies (ya lo está haciendo) y sus sesiones caducan pronto, creo que es razonablemente seguro y más seguro que hacer estas ejecuciones en un canal inseguro.


3
2018-01-14 14:57



En primer lugar, tiene un error en el código de regeneración de la sesión. El siguiente si siempre se evaluará como verdadero:

if ($rand != 1 || $rand != 3 || $rand != 5)

Si $rand es no 1, vuelve verdadero. Si $rand  es 1, entonces no son tres, y vuelve verdadero. Probablemente quisiste usar un and aquí.

En segundo lugar, no necesita MD5 el user_ip, o el user_agent instrumentos de cuerda. Si alguien puede acceder directamente a los datos de la sesión en tu servidor, estás tan metido en eso que los datos no te salvarán.

ACLARACIÓN: Como señalan SDC y crush en los comentarios, MD5 es bueno para contraseñas hash si lo tienes con sal. Esto significa que las contraseñas de sus usuarios generalmente aún son seguras, incluso si un ataque de Inyección SQL tiene éxito y su base de datos está expuesta al mundo. Sin embargo, si el servidor se ve comprometido y la sal se ve comprometida, es posible generar un conjunto de hash conocidos e intentar una búsqueda inversa de una contraseña específica. ¿Línea de fondo? Hash sus contraseñas de usuario, con una sal.

En tercer lugar, la mayoría de los agujeros de seguridad no provienen de sesiones de suplantación de identidad. Vienen de una mala comprobación de entrada. Un libro como Seguridad PHP esencial debería ser una buena introducción al tipo de verificación de entrada que debe hacer en un proyecto de PHP. En su defecto, al menos lea el sección de seguridad del Manual de PHP. Preste atención al bit de inyección de SQL. ¡Es genial!

Finalmente, estoy totalmente de acuerdo con el otro afiche en que debe usar SSL para asegurar la comunicación a su sitio web.


2
2018-01-14 15:09



Para ser sincero, creo que estás siendo demasiado precavido, pero no de una manera muy útil.

Si realmente está preocupado por la seguridad de la sesión, no intente hacerlo usted mismo. Use un parche de seguridad PHP como Suhosin. Deja que haga todo el trabajo duro por ti. Suhosin es un parche bien establecido para PHP. Incluye material que trata sobre todas las formas en que una sesión de PHP puede ser pirateada. Si lo tienes instalado, entonces no necesitas hacer nada adicional para asegurar tu sesión. Si no lo tienes instalado, definitivamente no puedes decir que eres súper paranoico con respecto a la seguridad.

En resumen, instale Suhosin (si aún no lo hizo) y olvídese de ello.

Pero para completar, haré algunos comentarios en su código actual, solo para señalar un par de cosas:

No estoy seguro de por qué crees que el hash MD5 hace la diferencia. Los hash MD5 se pueden descifrar en segundos, por lo que tenerlos en cualquier tipo de función de seguridad es completamente arbitrario. Puede ser texto sin formato. Dicho esto, realmente no veo la necesidad de que sean otra cosa que texto sin formato de todos modos: si un hacker ha logrado obtener los datos de la sesión para poder leer la dirección IP que contiene, entonces estás ya no se preocupan si saben la dirección IP o no.


0
2018-01-14 15:17



Seleccione la imagen para cargar:                                                                                                   ";         $ res = mysql_query ("SELECT` id`, `FirstName`,` LastName`, `Address`, `Password`,` Repassword`, `Birthday`,` Gender`, `user_image` FROM `registration`") o die (mysql_error ());         while ($ row = mysql_fetch_array ($ res))         {             $ id = $ row ['id'];             $ firstname = $ row ['FirstName'];             $ user_image = $ row ['user_image']; $ page. = "                                   $ firstname ";             } $ page. = "                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ";                 $ res_post = mysql_query ("SELECT post_info.post_info_id, post_info.id, post_info.post_info_desc, registration.FirstName FROM `post_info` join `registration` DONDE post_info.id = registration.id ordena por post_info.post_info_id desc ") o die (mysql_error ());                     while ($ row_post = mysql_fetch_array ($ res_post))                     {                     $ post_id = $ row_post ['post_info_id'];                     $ post_desc = $ row_post ['post_info_desc'];                     $ id = $ row_post ['id'];                     $ FirstName = $ row_post ['FirstName'];             $ page. = "

$ FirstName

$ post_desc

";                     } $ page. = "                    ";       include ('include / main_file.php');     ?>     

-1
2018-02-05 05:56



<?php

session_start();
$con=mysql_connect("localhost","root","");
$seldb=mysql_select_db('myfreind', $con);
$email=$_POST['txtEmail'];
$password=$_POST['txtPass'];
$res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`, `Password`, `Repassword`, `Birthday`, `Gender` FROM `registration` WHERE 
`Password`='$password' and  `FirstName`='$email'");
$num=mysql_num_rows($res);

if($num==1)
{
$row=mysql_fetch_array($res);
$id=$row['id'];
$firstname=$row['FirstName'];
$_SESSION['id']=$id;
$_SESSION['FirstName']=$firstname;
//echo $_SESSION['id'];
header('Location:main.php');
}else

{

header('Location:index.php?error');
}

?>

-2
2018-02-05 05:50



Preguntas populares