Autor Tema: [Debate] Para ustedes, que debería contenr un sistema segúro?  (Leído 903 veces)

Desconectado Atrix

  • PHPer@
  • **
  • Mensajes: 69
  • Karma: 2
  • Sexo: Masculino
  • Ah..?
    • Ver Perfil
[Debate] Para ustedes, que debería contenr un sistema segúro?
« en: 21 de Noviembre de 2011, 04:04:12 am »
La idea es, para aprender entre nosotros mismos y también para resolverme algunas dudas comentemos acerca de las características que debería tener un sistema de autenticación que sea lo más seguro posible.

Osea, que comentemos de qué debería tener, lo prioritario y lo erroneo en cuestiones de segúridad.

Además de que me ayudan, como dije... También aprenderemos entre nosostros...

Postdata: Esto sería a un nivel intermedio, así que funciones básicas y utilizadas comúnmente como htmlentities(); mysql_real_escape_string(); htmlspecialcharsstrip_tags(); entre otras quedarían descalificadas.

Comunidad PHPeros

[Debate] Para ustedes, que debería contenr un sistema segúro?
« en: 21 de Noviembre de 2011, 04:04:12 am »

Desconectado nmartin021

  • PHPero Avanzado
  • ****
  • Mensajes: 250
  • Karma: 9
    • Ver Perfil
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #1 en: 21 de Noviembre de 2011, 18:00:27 pm »
Siento decepcionarte, pero todo el mundo usa mysql_real_escape_string para los sistemas de autentificación (algunos usan htmlspecialchars($algo, ENT_QUOTES)), ya que es una función nativa (no hace falta hacer tu función, ya puedes usar esta directamente) y hasta ahora no me ha decepcionado nunca.

Desconectado Atrix

  • PHPer@
  • **
  • Mensajes: 69
  • Karma: 2
  • Sexo: Masculino
  • Ah..?
    • Ver Perfil
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #2 en: 21 de Noviembre de 2011, 20:21:58 pm »
Siento decepcionarte, pero todo el mundo usa mysql_real_escape_string para los sistemas de autentificación (algunos usan htmlspecialchars($algo, ENT_QUOTES)), ya que es una función nativa (no hace falta hacer tu función, ya puedes usar esta directamente) y hasta ahora no me ha decepcionado nunca.

Bueno, ya se que es algo que digamos "obligatorio", pero mi referencia es que comentemos acerca de módulos de segúridad que serían segúros..

Como en consultas, colocar la @ para evitar errores..

Ejemplo


@mysql_query("SELECT * FROM tienda WHERE articulo='domesticos' ORDER BY id LIMIT 100");

Desconectado CarlosRdrz

  • Moderador Global
  • PHPero Master
  • *****
  • Mensajes: 2.505
  • Karma: 131
  • Sexo: Masculino
  • A.k.a. TLX
    • Ver Perfil
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #3 en: 21 de Noviembre de 2011, 20:44:38 pm »
Hola a todos,

El uso de funciones como mysql_real_escape_string no siempre asegura un nivel de seguridad aceptable, aunque lo mejora.

Para empezar, hay muchas vulnerabilidades que evitar, y por lo tanto depende mucho del tipo de login, autentificación o formulario.

1. Para evitar inyecciones SQL es necesario usar siempre mysql_real_escape_string en cada una de las variables que se pasan a la base de datos, y además de eso, colocar todas las variables entrecomilladas. Me explico:

$id 
mysql_real_escape_string($_POST['id'])
mysql_query("SELECT ... WHERE id={$id}"); // VULNERABLE
mysql_query("SELECT ... WHERE id='{$id}' "); // NO VULNERABLE


2. Además, todos los parámetros deben pasar por un filtro que evite etiquetas HTML para evitar ataques por XSS. Ya hemos hablado mucho de esto: htmlentities, strip_tags, specialchars y demás.
La mayoría de la gente suele evitar XSS en username, nombre, apellidos... pero es necesario pasarlo en TODOS los campos.
Un campo de web puede contener código XSS, un campo email también y todos los campos pueden contenerlo.

Una máxima en seguridad web es asegurar TODOS, ABSOLUTAMENTE TODOS los datos que se insertan en una web, tengan la importancia en la lógica del script que tengan.

3. Además de eso, si usas cookies para permanecer en el login, también deben asegurarse los datos de las cookies, contra XSS y contra SQLi. Vuelvo a repetir, todo lo que se envía a una web y va a ser guardado o procesado debe pasar por esos filtros.

4. No creo que sea el caso, pero en los login multipasos hay que tener MUCHO cuidado, porque pueden ser fácilmente salteados, variando la secuencia de páginas para ingresar y modificando campos que se envían entre pasos.

5. Mucho cuidado también con los campos HIDDEN. Los campos hidden son campos como otros cualquiera, y pueden modificarse fácilmente con herramientas que se pueden encontrar con facilidad. De nuevo, TODO lo que entra y se procesa en la web tiene que pasar el filtro Anti-XSS y Anti-SQLi

6. El sistema de login debe tener un sistema captcha. Esta medida se debe combinar con sugerir FUERTEMENTE a los usuarios colocar una clave segura. Además, debe colocarse una longitud de password mínimo razonable, y intentar usar el máximo rango de caracteres posibles. Lo ideal sería numeros, letras y caracteres especiales ($%&# y demás) pero esto depende en gran medida del usuario, y hay que tener en cuenta que probablemente la mayoría no lo harán.

7. Un fallo muy común es indicar en un login cual de los dos campos (usuario o contraseña) no es introducido correctamente. Un login en el que se indique "El usuario introducido no existe" se puede bruteforcear (es decir, introducir muchos valores en poco tiempo con un automatismo) para sacar usuarios que existen a partir de los errores que se devuelven, como el mencionado anteriormente, y a partir de ahí bruteforcear el campo de passwords para sacar una contraseña en un nombre de usuario que conozcamos.
Esta debilidad también se encuentra en un registro. Cuando se introduce un usuario ya existente normalmente se le suele advertir al usuario de que ese nombre ya está cogido, con lo que se puede bruteforcear un registro de usuarios para ver que nombres de usuario existen, y así conseguir passwords débiles.
Soluciones: usar captcha en el login tras un número de intentos fallidos (por ejemplo 3, o 5) y igual en el registro de usuarios. Introducir un captcha directamente puede ser muy molesto para los usuarios, así que solo introducelo cuando falle varias veces (imagina que tubieras que rellenar un captcha cada vez que quieres acceder a Facebook o Twitter).

8. Cuidado con la forma en la que contabilizas los intentos fallidos en formularios. Si envías una cookie con el número de intentos fallidos, y haces saltar tu sistema antibot (como captcha) despues de, por ejemplo, 5 intentos, se podría automatizar un bot que borrara las cookies cada 3 o 4 intentos de forma que no se detectaría.
Utilizar una sesión parece lo mas adecuado, pero hay que tener cuidado con que guardar. El campo $_SERVER['REMOTE_ADDR'] es más seguro que $_SERVER['HTTP_X_FORWARDED_FOR'], ya que esta última puede modificarse fácilmente.

9. Si es posible, nunca muestres keys de la base de datos (como las id) en tu sitio web. Evita cosas como http://miweb.com/usuarios.php?id=2
Con cosas así puede saberse que id pertenece a que usuario, y usar esa información para explotar otra vulnerabilidad.

10. Cuidado con los file paths! He visto muchos "sistemas de modulación" (como se le suele decir por aquí) que al incluir archivos no comparan con unos archivos esperados, y la gente puede incluir cualquier archivo con un poco de imaginación. http://miweb.com/noticias/?pagina=../index.php~
Lo correcto es crear un array con páginas aceptables, por ejemplo array("noticia1.php", "noticia2.php", etc); y comparar la variable pasada con esa array (con la función in_array) y si no existe coincidencia mostrar un error.

11. Cuidado con el archivo robots
Cualquiera puede leer ese archivo, no solo los buscadores, y por lo tanto meter ahí direcciones como paneles de administración puede acabar en filtrar urls privadas.

12. Nunca creas que por llamar a un directorio asdasdas_dasd12312r no lo van a descubrir. Poner un nombre de directorio aleatorio NO ES SEGURO, habrá que implementar un sistema de autentificación o login para ese directorio, pero desde luego hay que protegerlo. Es cierto que puede dificultar que lo encuentren, pero puede filtrarse fácilmente, es mejor no jugársela.

13. Recuerda que muchas de las variables en $_SERVER y en $_COOKIE y demás pueden sobreescribirse y modificarse en el cliente, por lo tanto no es buena idea fiarse de ellas para temas de autentificación. Permitir a un usuario entrar en X página si su navegador es "Navegador de MiWeb.com" no se puede considerar seguro porque cualquiera puede modificar esa variable y aplicarse el título de ese navegador sin poseerlo. Lo que quiero decir básicamente es que NUNCA puedes fiarte de lo que te envíe un usuario.

14. Cuidado con los permisos de los archivos y directorios. Tener permisos 777 en todos los directorios puede explotarse mediante otra vulnerabilidad. Cada directorio y archivo debe tener los permisos que necesita. Ni más, ni menos.

15. Vulnerabilidades en la lógica de los scripts PHP puede haber innumerables, eso ya depende de tu forma de programar. Ten siempre cuidado con lo que programas, y nunca dejes nada suelto. Nunca supongas "Bah, esto el usuario no lo sabrá." o cosas por el estilo. Siempre debes imaginar que va a existir un usuario malintencionado que va a querer jugártela.

16. Como te han dicho, cuando estés en produccion (dejes de hacer pruebas) es mejor usar @ en la funciones para filtrar errores que podrían dar información de más a usuarios malintencionados.

Si creen que algo está mal o tienen una mejor idea no duden en comentarlo.
Un saludo, y perdón por el post tan largo.
« Última modificación: 21 de Noviembre de 2011, 20:48:18 pm por CarlosRdrz »
La dedicación de mi respuesta sera directamente proporcional a la dedicación de tu pregunta.
Hacer códigos que entiendan las máquinas es fácil, lo difícil y realmente útil es hacer códigos que entiendan las personas.
http://twitter.com/CarlosRdrz
http://www.carlosrdrz.es

Desconectado SoyJoaquin.

  • PHPero Master
  • ******
  • Mensajes: 2.737
  • Karma: 131
  • Sexo: Masculino
  • ส้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้ส้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้ Problem?
    • Ver Perfil
    • IsoMap
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #4 en: 21 de Noviembre de 2011, 22:05:20 pm »
Hola a todos,

El uso de funciones como mysql_real_escape_string no siempre asegura un nivel de seguridad aceptable, aunque lo mejora.

Para empezar, hay muchas vulnerabilidades que evitar, y por lo tanto depende mucho del tipo de login, autentificación o formulario.

1. Para evitar inyecciones SQL es necesario usar siempre mysql_real_escape_string en cada una de las variables que se pasan a la base de datos, y además de eso, colocar todas las variables entrecomilladas. Me explico:

$id 
mysql_real_escape_string($_POST['id'])
mysql_query("SELECT ... WHERE id={$id}"); // VULNERABLE
mysql_query("SELECT ... WHERE id='{$id}' "); // NO VULNERABLE


2. Además, todos los parámetros deben pasar por un filtro que evite etiquetas HTML para evitar ataques por XSS. Ya hemos hablado mucho de esto: htmlentities, strip_tags, specialchars y demás.
La mayoría de la gente suele evitar XSS en username, nombre, apellidos... pero es necesario pasarlo en TODOS los campos.
Un campo de web puede contener código XSS, un campo email también y todos los campos pueden contenerlo.

Una máxima en seguridad web es asegurar TODOS, ABSOLUTAMENTE TODOS los datos que se insertan en una web, tengan la importancia en la lógica del script que tengan.

3. Además de eso, si usas cookies para permanecer en el login, también deben asegurarse los datos de las cookies, contra XSS y contra SQLi. Vuelvo a repetir, todo lo que se envía a una web y va a ser guardado o procesado debe pasar por esos filtros.

4. No creo que sea el caso, pero en los login multipasos hay que tener MUCHO cuidado, porque pueden ser fácilmente salteados, variando la secuencia de páginas para ingresar y modificando campos que se envían entre pasos.

5. Mucho cuidado también con los campos HIDDEN. Los campos hidden son campos como otros cualquiera, y pueden modificarse fácilmente con herramientas que se pueden encontrar con facilidad. De nuevo, TODO lo que entra y se procesa en la web tiene que pasar el filtro Anti-XSS y Anti-SQLi

6. El sistema de login debe tener un sistema captcha. Esta medida se debe combinar con sugerir FUERTEMENTE a los usuarios colocar una clave segura. Además, debe colocarse una longitud de password mínimo razonable, y intentar usar el máximo rango de caracteres posibles. Lo ideal sería numeros, letras y caracteres especiales ($%&# y demás) pero esto depende en gran medida del usuario, y hay que tener en cuenta que probablemente la mayoría no lo harán.

7. Un fallo muy común es indicar en un login cual de los dos campos (usuario o contraseña) no es introducido correctamente. Un login en el que se indique "El usuario introducido no existe" se puede bruteforcear (es decir, introducir muchos valores en poco tiempo con un automatismo) para sacar usuarios que existen a partir de los errores que se devuelven, como el mencionado anteriormente, y a partir de ahí bruteforcear el campo de passwords para sacar una contraseña en un nombre de usuario que conozcamos.
Esta debilidad también se encuentra en un registro. Cuando se introduce un usuario ya existente normalmente se le suele advertir al usuario de que ese nombre ya está cogido, con lo que se puede bruteforcear un registro de usuarios para ver que nombres de usuario existen, y así conseguir passwords débiles.
Soluciones: usar captcha en el login tras un número de intentos fallidos (por ejemplo 3, o 5) y igual en el registro de usuarios. Introducir un captcha directamente puede ser muy molesto para los usuarios, así que solo introducelo cuando falle varias veces (imagina que tubieras que rellenar un captcha cada vez que quieres acceder a Facebook o Twitter).

8. Cuidado con la forma en la que contabilizas los intentos fallidos en formularios. Si envías una cookie con el número de intentos fallidos, y haces saltar tu sistema antibot (como captcha) despues de, por ejemplo, 5 intentos, se podría automatizar un bot que borrara las cookies cada 3 o 4 intentos de forma que no se detectaría.
Utilizar una sesión parece lo mas adecuado, pero hay que tener cuidado con que guardar. El campo $_SERVER['REMOTE_ADDR'] es más seguro que $_SERVER['HTTP_X_FORWARDED_FOR'], ya que esta última puede modificarse fácilmente.

9. Si es posible, nunca muestres keys de la base de datos (como las id) en tu sitio web. Evita cosas como http://miweb.com/usuarios.php?id=2
Con cosas así puede saberse que id pertenece a que usuario, y usar esa información para explotar otra vulnerabilidad.

10. Cuidado con los file paths! He visto muchos "sistemas de modulación" (como se le suele decir por aquí) que al incluir archivos no comparan con unos archivos esperados, y la gente puede incluir cualquier archivo con un poco de imaginación. http://miweb.com/noticias/?pagina=../index.php~
Lo correcto es crear un array con páginas aceptables, por ejemplo array("noticia1.php", "noticia2.php", etc); y comparar la variable pasada con esa array (con la función in_array) y si no existe coincidencia mostrar un error.

11. Cuidado con el archivo robots
Cualquiera puede leer ese archivo, no solo los buscadores, y por lo tanto meter ahí direcciones como paneles de administración puede acabar en filtrar urls privadas.

12. Nunca creas que por llamar a un directorio asdasdas_dasd12312r no lo van a descubrir. Poner un nombre de directorio aleatorio NO ES SEGURO, habrá que implementar un sistema de autentificación o login para ese directorio, pero desde luego hay que protegerlo. Es cierto que puede dificultar que lo encuentren, pero puede filtrarse fácilmente, es mejor no jugársela.

13. Recuerda que muchas de las variables en $_SERVER y en $_COOKIE y demás pueden sobreescribirse y modificarse en el cliente, por lo tanto no es buena idea fiarse de ellas para temas de autentificación. Permitir a un usuario entrar en X página si su navegador es "Navegador de MiWeb.com" no se puede considerar seguro porque cualquiera puede modificar esa variable y aplicarse el título de ese navegador sin poseerlo. Lo que quiero decir básicamente es que NUNCA puedes fiarte de lo que te envíe un usuario.

14. Cuidado con los permisos de los archivos y directorios. Tener permisos 777 en todos los directorios puede explotarse mediante otra vulnerabilidad. Cada directorio y archivo debe tener los permisos que necesita. Ni más, ni menos.

15. Vulnerabilidades en la lógica de los scripts PHP puede haber innumerables, eso ya depende de tu forma de programar. Ten siempre cuidado con lo que programas, y nunca dejes nada suelto. Nunca supongas "Bah, esto el usuario no lo sabrá." o cosas por el estilo. Siempre debes imaginar que va a existir un usuario malintencionado que va a querer jugártela.

16. Como te han dicho, cuando estés en produccion (dejes de hacer pruebas) es mejor usar @ en la funciones para filtrar errores que podrían dar información de más a usuarios malintencionados.

Si creen que algo está mal o tienen una mejor idea no duden en comentarlo.
Un saludo, y perdón por el post tan largo.


1- Lo que dijiste en el paso 10, seria eficaz ademas usar file_exist ya que comprueba la existencia de archivos del mismo servidor.

2- Aparte del Captcha como ya dijiste, existe un error muy poco conocido en donde puedo decir que aproximadamente el 40% o 50% de las paginas webs son vulnerables. Resulta en poder manipular formularios mediante JavaScript o cURL, no me acuerdo del nombre pero si mal no estoy son 4 siglas.

Por ejemplo:
Tu estas logueado en www.ejemplo.com, yo te paso un supuesto link que puede estar camuflajeado, en ese link de mi servidor yo puedo manipular los formularios de la pagina en donde te encuentras conectado, básicamente seria el poder usar tu cuenta mediante código sin que tu mismo te llegues a dar cuenta. En esa web donde yo pueda acceder a todos los paneles podre hacer todo en donde no pida la contraseña para verificar una acción, en todas esas acciones que yo realice aparecerá con tu IP , es indetectable.

3- Recomendaría usar filtros de tiempo en herramientas como comentarios para evitar un ataque masivo.
4- Proteger los directorios que no posean un index con .htaccess
5- Verificar siempre los datos del usuario tanto al registrarse, conectarse, etc para mantener un historial de las ultimas direcciones IP de ese usuario.
6- Tener en cuenta que todo lo que sea visible en el código fuente de la pagina en si (HTML) puede ser editado por el visitante para alterar su funcionamiento. Si tienes que verificar o comprobar algo, hazlo tanto en el lado del cliente como del servidor. ¿Por que?, en el lado del cliente para ahorrarle peticiones innecesarias al servidor y en el lado del servidor en caso de que alguien edite el cliente.
7- Un error común es que en un registro, elimina tags HTML y si ese usuario ya se encuentra registrado, se duplicara. Ejemplo:
Si registro <h1>Hola<h1> y Hola ya se encuentra registrado, al momento de registrar el que contenga las etiquetas html y las elimines este duplicara el usuario.
8- Tratar de optimizar lo mas posible el código cosa que rinda mas la velocidad de carga y el peso del archivo.
9- Algo un muy común es que el usuario con IP dinámica no pueda ser baneado, pues juegate con las cookies, session y demás, cosa que aunque cambie la ip y que llegue a estar la cookie de baneo activada o la session, lo vuelva a banear con la nueva ip.
10- Esconder los links usando .htaccess para dificultar hallar el archivo original.

Saludos
Twitter: @JoakoM010



Desconectado nmartin021

  • PHPero Avanzado
  • ****
  • Mensajes: 250
  • Karma: 9
    • Ver Perfil
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #5 en: 25 de Noviembre de 2011, 21:53:44 pm »
@CarlosRdRz:
Muy bien explicado, felicidades. Como siempre, nos enseñas los fallos y cómo protegernos. Te ganas un K+.

@SoyJoaquin.:
Tienes un error. Aunque uses file_exists() sigue habiendo una vulnerabilidad, y es que tu puedes incluir archivos de los directorios de ese mismo servidor (LFI, Local File Inclusion)... por ejemplo, si ya tienes la pass de una web que hackeaste pero te falta el usuario, con una vulnerabilidad así podría incluir 2 veces el mismo archivo, generar un error y conseguir tu usuario.
Además, no tienes por qué usar @, ya que gasta mucha memoria y es muy lento. Es mejor poner el error reporting a 0:
<?php error_reporting(0); ?>
« Última modificación: 25 de Noviembre de 2011, 21:56:09 pm por nmartin021 »

Desconectado SoyJoaquin.

  • PHPero Master
  • ******
  • Mensajes: 2.737
  • Karma: 131
  • Sexo: Masculino
  • ส้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้ส้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้ Problem?
    • Ver Perfil
    • IsoMap
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #6 en: 25 de Noviembre de 2011, 22:56:22 pm »
@CarlosRdRz:
Muy bien explicado, felicidades. Como siempre, nos enseñas los fallos y cómo protegernos. Te ganas un K+.

@SoyJoaquin.:
Tienes un error. Aunque uses file_exists() sigue habiendo una vulnerabilidad, y es que tu puedes incluir archivos de los directorios de ese mismo servidor (LFI, Local File Inclusion)... por ejemplo, si ya tienes la pass de una web que hackeaste pero te falta el usuario, con una vulnerabilidad así podría incluir 2 veces el mismo archivo, generar un error y conseguir tu usuario.
Además, no tienes por qué usar @, ya que gasta mucha memoria y es muy lento. Es mejor poner el error reporting a 0:
<?php error_reporting(0); ?>

Yo no fui el que dio el ejemplo de @, fue Atrix.
Saludos
Twitter: @JoakoM010



Desconectado nmartin021

  • PHPero Avanzado
  • ****
  • Mensajes: 250
  • Karma: 9
    • Ver Perfil
Re:[Debate] Para ustedes, que debería contenr un sistema segúro?
« Respuesta #7 en: 25 de Noviembre de 2011, 23:00:15 pm »
Yo no fui el que dio el ejemplo de @, fue Atrix.
Saludos
Ups! Lo siento, es que a veces me lío con los foros smf :D

Perdon de nuevo, no era mi intención.