25 de septiembre de 2019

No utilizar el número IMEI como identificador de usuario en aplicaciones móviles

Es una indudable ventaja el hecho de poder obtener el número IMEI de un dispositivo móvil desde una aplicación para cualquiera de las plataformas móviles de la actualidad, sin embargo utilizarlo como identificador único para acceder a un servicio web puede ser un error bastante costoso.

La realidad es que si bien el Numero IMEI (International Mobile Equipment Identity)
es un número único e irrepetible pregrabado en todos los equipos GSM que lo identifica a nivel mundial, es muy tentador asociar ese número a un usuario determinado, por lo que empieza a ser una práctica convencional.

Sin embargo, el paso de este número específico como parámetro de identificación a un servicio web o rutina, inclusive a través de una conexión por socket sin utilizar cifrado es una práctica muy riesgosa, por una parte debido a que dicho número es de fácil obtención por parte de cualquier persona con acceso al dispositivo, y por otra porque la intercepción de dicho número por parte del atacante puede implicar serios riesgos en sistemas de identificación que lo usen.

Empecemos con un simple ejemplo que funciona en absolutamente todos los teléfonos GSM. Simplemente pulsemos la secuencia de caracteres *#06# en el teclado de un dispositivo e inmediatamente obtendremos una ventana en la que aparece nuestro número IMEI.

Pero eso no es todo, el número IMEI además en su composición guarda información específica acerca del dispositivo, que al cotejarse en una base de datos puede revelar demasiados datos acerca de nuestro teléfono. Para comprobarlo, obtengan su número IMEI mediante la secuencia de teclado que explicamos en el párrafo anterior e introduzca el mismo en este sitio: http://www.imei.info/ . Obtentrán una pantalla informativa impresionante como la que les muestro a continuación:



Definitivamente asociar un usuario a un teléfono móvil puede ser extremadamente útil en aplicaciones de seguridad de todo tipo entre ellas aplicaciones para realizar transacciones desde el teléfono o para obtener acceso. La mayoría de los sistemas operativos móviles permiten acceder a números únicos de identificación del dispositivo derivados del IMEI o de algún otro número como por ejemplo la identificación del dispositivo de red wireless. Si aún así decides usar el IMEI, entonces no lo pases jamás como parámetro sin combinar y cifrar.




OWASP TOP 10 2017

Nuevamente OWASP nos hace llegar la lista de las más importantes vulnerabilidades en lo referente a desarrollo web en su lista del 2017 Top 10.

OWASP Top 10 2017

Riesgos en Seguridad de Aplicaciones

A1:2017 Inyección

Las fallas de inyección, como SQL, NoSQL, OS o LDAP ocurren cuando se envían datos no
confiables a un intérprete, como parte de un comando o consulta. Los datos dañinos del atacante
pueden engañar al intérprete para que ejecute comandos involuntarios o acceda a los datos sin
la debida autorización.


A2:2017 Pérdida de Autenticación

Las funciones de la aplicación relacionadas a autenticación y gestión de sesiones son
implementadas incorrectamente, permitiendo a los atacantes comprometer usuarios y
contraseñas, token de sesiones, o explotar otras fallas de implementación para asumir la
identidad de otros usuarios (temporal o permanentemente).



A3:2017 Exposición de datos sensible

Muchas aplicaciones web y APIs no protegen adecuadamente datos sensibles, tales como
información financiera, de salud o Información Personalmente Identificable (PII). Los atacantes
pueden robar o modificar estos datos protegidos inadecuadamente para llevar a cabo fraudes
con tarjetas de crédito, robos de identidad u otros delitos. Los datos sensibles requieren métodos
de protección adicionales, como el cifrado en almacenamiento y tránsito.



A4:2017 Entidades Externas XML (XXE)

Muchos procesadores XML antiguos o mal configurados evalúan referencias a entidades
externas en documentos XML. Las entidades externas pueden utilizarse para revelar archivos
internos mediante la URI o archivos internos en servidores no actualizados, escanear puertos de
la LAN, ejecutar código de forma remota y realizar ataques de denegación de servicio (DoS).



A5:2017 Pérdida de Control de Acceso

Las restricciones sobre lo que los usuarios autenticados pueden hacer no se aplican
correctamente. Los atacantes pueden explotar estos defectos para acceder, de forma no
autorizada, a funcionalidades y/o datos, cuentas de otros usuarios, ver archivos sensibles,
modificar datos, cambiar derechos de acceso y permisos, etc.



A6:2017 Configuración de Seguridad Incorrecta

La configuración de seguridad incorrecta es un problema muy común y se debe en parte a
establecer la configuración de forma manual,
ad hoc o por omisión (o directamente por la falta de
configuración). Son ejemplos:
S3 buckets abiertos, cabeceras HTTP mal configuradas, mensajes
de error con contenido sensible, falta de parches y actualizaciones,
frameworks, dependencias y
componentes desactualizados, etc.



A7:2017 Secuencia de Comandos en Sitios Cruzados (XSS)

Los XSS ocurren cuando una aplicación toma datos no confiables y los envía al navegador web
sin una validación y codificación apropiada; o actualiza una página web existente con datos
suministrados por el usuario utilizando una API que ejecuta
JavaScript en el navegador. Permiten
ejecutar comandos en el navegador de la víctima y el atacante puede secuestrar una sesión,
modificar (
defacement) los sitios web, o redireccionar al usuario hacia un sitio malicioso.

A8:2017 Deserialización Insegura

Estos defectos ocurren cuando una aplicación recibe objetos serializados dañinos y estos objetos
pueden ser manipulados o borrados por el atacante para realizar ataques de repetición,
inyecciones o elevar sus privilegios de ejecución. En el peor de los casos, la deserialización
insegura puede conducir a la ejecución remota de código en el servidor.



A9:2017 Componentes con vulnerabilidades conocidas

Los componentes como bibliotecas, frameworks y otros módulos se ejecutan con los mismos
privilegios que la aplicación. Si se explota un componente vulnerable, el ataque puede provocar
una pérdida de datos o tomar el control del servidor. Las aplicaciones y API que utilizan
componentes con vulnerabilidades conocidas pueden debilitar las defensas de las aplicaciones y
permitir diversos ataques e impactos.



A10:2017 Registro y Monitoreo Insuficientes 

El registro y monitoreo insuficiente, junto a la falta de respuesta ante incidentes permiten a los
atacantes mantener el ataque en el tiempo, pivotear a otros sistemas y manipular, extraer o
destruir datos. Los estudios muestran que el tiempo de detección de una brecha de seguridad es
mayor a 200 días, siendo típicamente detectado por terceros en lugar de por procesos internos.


Para obtener mayor información acerca de cada una de estas vulnerabilidades pueden bajar el documento impreso de las mismas en castellano en https://www.owasp.org/images/5/5e/OWASP-Top-10-2017-es.pdf

Espero les sea útil.



Redactado por Mauro Maulini R.

20 de septiembre de 2019

¿Por qué utilizar Cookies "Seguros"?

Uno de los problemas que presentamos los desarrolladores es el control de los Cookies usados en transacciones seguras. El primer inconveniente que se presenta cuando usamos cookies bajo protocolo SSL o TSL (el conocido HTTPS con la S al final de "secure") es que estos cookies si no tomamos las debidas precauciones en el manejo de los mismos, persisten si el usuario deja la transacción segura para continuar visitando otras áreas de nuestro sitio, lo que convierte su contenido en interceptable.

Otro de los casos que permite revelar las cookies que pasan a través de una conexión segura y que además es muy común, es aquel en el que en una misma página solicitada por HTTPS, solicitamos recursos por simple HTTP, como por ejemplo una imagen en una cabecera que se usa indistintamente en páginas seguras y no seguras. En la cabecera HTTP de la solicitud de dicha imagen el servidor envía todos los cookies del dominio que hace la solicitud en los cuales por supuesto incluye aquellos que se usan para el control de sesión y otras variables de la aplicación "ya no tan segura".

Es importante recordar que el protocolo HTTP es "stateless" o en otras palabras, no maneja estado de sesión, por lo que cada conexión se realiza como si fuera la primera. Precisamente para poder emular un estado de sesión es que las diferentes plataformas de desarrollo utilizan el concepto de un identificador de sesión (session ID), que no es más que un cookie que funciona como identificador de sesión y al cual se asocia un área de memoria en el servidor en la cual se guardan las variables de sesión.

En fin, como ya habrán podido captar, es necesario para la seguridad de la aplicación proteger los cookies, y para ello el protocolo HTTP 1.1 soporta un parámetro para cada cookie conocido como "secure flag" que al ser activado no permite que los cookies con dicho atributos sean transmitidos en conexiones HTTP simple o inseguras.

Este atributo se puede agregar por cada cookie o en general, y cada plataforma conocida lo soporta. Por ejemplo:

En PHP
Coloque en true el parámetro httponly:
setcookie( name, value, expire, path, domain, secure, httponly);

En el php.ini:
session.cookie_secure = on

En JSP /Java Server Pages:

Cookie holaCookie = new Cookie("",text);
holaCookie.setSecure(true);

En ASP.NET
Coloque en el web.config la siguiente línea:

<httpCookies requireSSL="true" /> 

Para hacerlo de forma explícita por cada cookie:

HttpCookie cookie = new HttpCookie("nombre");
cookie.Secure = True;
cookie.Value = "José";

8 de septiembre de 2019

Leer correctamente los datos provenientes del Request

Un "error" muy común de los programadores web en cuanto a la seguridad de sus aplicaciones, es acceder directamente a las variables enviadas desde las solicitudes recibidas desde la colección genéricas Request, como la clase "Request" en ASP o la variable $_REQUEST en PHP:

En ASP:
String nombre = Request["name"];

En PHP:
$nombre = $_REQUEST['name'];

Si bien esta forma de hacerlo es "correcta" lingüisticamente hablando, es bueno recordar que las variables de input tradicionales de una solicitud web suelen llegar por tres diferentes vías: por el método GET, el método POST o a través de cookies. Cuando usamos la clase Request o la variable $_REQUEST según el caso del lenguaje (ASP o PHP) estamos solicitando información en una colección genérica que agrupa las tres opciones (y otras más), y si bien es mucho más fácil y limpio de usar, este método infiere en el error por omisión, de admitir que un dato específico llegue a nuestras páginas por cualquiera de los tres métodos.



El hacker entonces podría perfectamente modificar el valor de un cookie introduciéndolo desde el URL, podría también modificar valores de un formulario que viaja por POST atacándolo desde un simple enlace enviado por e-mail. Esto se debe a que nuestra aplicación al solicitar los datos no diferencia por cual de los tres métodos están siendo enviados. Las implicaciones de poder infectar los cookies del navegador del usuario a través de un URL pueden ser enormes, pero no vamos a detallar esa práctica en este artículo.

Es imperativo, utilizar el método determinado según el acceso por el que debemos recibir los datos y evitar usar el método genérico Request. Ejemplo:

En ASP:
String nombre = Request.QueryString["name"]; // para el método GET
String nombre = Request.Form["name"]; // para el método POST
String nombre = Request.Cookies["name"]; // 

En PHP:
$nombre = $_GET['name'];
$nombre = $_POST['name'];
$nombre = $_COOKIE['name'];

En el lenguaje JSP (Java Server Pages) el problema es aún más grave debido a que el lenguaje no diferencia con el método Request.getParameter("name") si la solicitud es recibida por POST, GET o es un Cookie. En este caso se recomiendan o bien utilizar el método Request.getMethod(), que nos aclara por donde han llegado los datos, simplemente utilizar la tecnología de servlets que si diferencia entre ambos métodos con doGet(request, response) y doPost(request, response).


Redactado por Mauro Maulini R.

4 de septiembre de 2019

Confiar en que el viewState de una página en Asp.NET está cifrado: ¡Error!

Uno de los errores más comunes de seguridad de los programadores de Asp.NET que utilizan "web forms" en sus aplicaciones, es creer que el "viewState" (ese campo oculto que se puede ver en todas las páginas desarrolladas con "web forms" que contiene un cantidad apreciable de caracteres ilegible) está cifrado.

El viewState es un repositorio de información en el que se apoyan los "web forms" para guardar los datos de los diferentes componentes o áreas de una página entre llamada y llamada al servidor. Incluso es accesible desde el código y podemos guardar información allí para usarla en de forma eficiente en nuestras páginas por ejemplo:

ViewState["password"] = thepassword;

Pero no es una buena práctica colocar información sensible como un password en dicho repositorio, debido a que la creencia de que el viewState está cifrado es completamente errónea. El viewState no es cifrado entre viaje y viaje al servidor sino codificado. Si usted conoce algo de criptografía entenderá que la diferencia entre cifrar y codificar es muy obvia, caso contrario permítame explicarle de forma muy resumida un importante detalle a la hora de proteger sus datos: para descodificar solo es necesario conocer el algoritmo en el cual el texto fue codificado, mientras que pare descifrar es necesario conocer una clave de cifrado además del algoritmo y esta no viaja junto al texto cifrado. 

Por lo anterior entenderá que si sabemos el algoritmo con el que el viewState es codificado, solo tenemos que usarlo en reversa para decodificarlo. Y bien ese algoritmo es el conocido Base64. Compruébelo usted mismo introduciendo el viewState de una página Asp.NET en este decodificador de viewState gratuito en línea: http://ignatu.co.uk/ViewStateDecoder.aspx 

Ante este problema tenemos dos soluciones: 
  1. No colocar nunca información delicada en el viewState
  2. Cifrar el viewState o cifrar la información que coloquemos en él.

La primera opción no necesita explicación, la segunda si amerita de algo de información adicional. El viewState, desde la versión de Asp.NET 2.0 en adelante también puede ser cifrado. Usted puede decidir hacerlo en absolutamente todo el sitio web colocando el siguiente atributo en la sección <pages> del archivo web.config:

<pages viewStateEncryptionMode="Always">

Sin embargo hay que tomar en cuenta que el cifrado puede reducir la velocidad de respuesta sobretodo si estamos en un sitio de alto consumo, por lo que podemos también utilizar el cifrado del viewState a nivel de cada página colocando el siguiente atributo en la cabecera <% @ Page >

<% @ Page Language="C#" AutoEventWireup="true" CodeBehind="login1.aspx.cs" ViewStateEncryptionMode="Always" %>

Espero que este truco e información sean de utilidad para los desarrolladores en Asp.NET.

Entradas populares