La realidad de los ataques en la web

Mientras escribo sobre las distintas tipologías de defensas que podemos construir frente a los ataques que pueden, o no, sufrir nuestras APIs. Me planteo cómo de realista es pensar que un servicio va a ser atacado, y cuál es la distribución posible de estas tipologías de ataques.

Una primera parada en nuestro viaje es el WHID, Web Hacking Incident Database (link: http://projects.webappsec.org/w/page/13246995/Web-Hacking-Incident-Database), donde se recoge la distribución de los diferentes ataques. Aunque bien es cierto que la información está un poco desfasada (2010) la utilizo como línea base para establecer comparaciones con el estado actual.

grafico_ataques_2010

 

En los últimos post ya mencioné como protegernos contra dos de estos ataques, que parecen bastante significativos:

Ataques de DoS/DDoS (denegación de servicio)

Ataques de inyección de código

 

Pero a decir verdad me parece significativo que el 32% de los ataques tengan un método desconocido.

 

Si miramos a la última estadística, junio 2014 , el 27,4% sigue siendo un método de ataque desconocido. Cuatro años después el porcentaje se mantiene prácticamente invariante.

 

grafico_ataques_2014

Y vemos además que DoS / DDoS sigue creciendo, la técnica de inyección de código parece menos relevante (pero no podemos por ello dejar de protegernos frente a ella).

Adicionalmente a la estadística de Junio, hoy vemos cómo un nuevo ataque se ha hecho público en el que información sobre cuentas de correo, direcciones y números de teléfono de 20.000 usuarios ha sido extraida inpunemente del sitio web del BCE.

 

Advertisements

Protección de APIs frente a Inyección de código

Una de las amenazas a las que cualquier API está expuesta es el ataque de inyección (sql injection, ldap injection ), que no por conocido deja de estar entre la lista de ataques que mejores resultados producen a la hora de obtener acceso a grandes cantidades de información, o la mejor forma de destruir la información existente.

¿De qué forma podemos detectar que al recibir una llamada a un método esta incluye algún contenido malicioso que pueda ocasionar daños al servicio expuesto?

Debemos tener en cuenta que el contenido malicioso puede encontrarse en cualquier cabecera http, en la query string, o en el propio contenido de la petición.

El mecanismo habitual es contrastar con un conjunto de expresiones regulares que definan los diferentes casos de inyección: select * from users, delete from users, ‘ or 1=1–, ‘ or ”=’.

Una vez definido el conjunto de expresiones regulares el objetivo es aplicarlo a las distintas llamadas al API que queremos securizar.

Algún ejemplo de expresiones regulares, para los casos que comento, serían:

delete from users

       (?i)\s*delete\s*\w*\W*\s+from

‘ or ”=’

       (?i)’\s+or(‘|”|\s+)

¿Pero cuál es exactamente la base del problema?

Normalmente cuando accedemos a una base de datos tenemos diversas formas de hacerlo:

a)      Creamos una consulta, le añadimos el parámetro que hemos recibido en la llamada al método del API, y posteriormente la ejecutamos.

String query = “SELECT user FROM users WHERE user_name = ” + request.getParameter(“customerName”);

 

b)      Usamos un prepared statement, al que pasamos como parámetro aquél que hemos recibido en la llamada al método del API, y posteriormente lo ejecutamos.

String cName = request.getParameter(“customerName”);

String query = “SELECT user FROM users WHERE user_name = ? “;

PreparedStatement pstmt = connection.prepareStatement( query );

pstmt.setString( 1, cName);

 

c)       Utilizar procedimientos almacenados en la base de datos, a los que llamamos desde nuestra API.

        String cName = request.getParameter(“customerName”);  CallableStatement cs = connection.prepareCall(“{call sp_getAccountBalance(?)}”);        cs.setString(1, cName);

 

El defecto que plantea utilizar la primera opción, que es la más usada, es que permite que cualquiera que sea el contenido del parámetro “customerName” va a ser usado dentro de la query que se lanza ( select * from xxxx, drop table yyy, … ), y sólo los privilegios que dicho usuario tenga dentro del gestor de base de datos le frenarán de parar el motor de base de datos, o cualquier otra fechoría.

Aunque siempre debe verificarse que los parámetros no contengan ninguna inyección de código, las opciones b y c son más seguras y sólo depende del diseño de la solución el usar una u otra.

¿Cuál es la recomendación? Utilizar una solución de seguridad perimetral que impida que dichas llamadas a los métodos del API crucen siquiera la DMZ, y a su vez detectada la amenaza notificar al SIEM para que sirva de punto de detección de otros patrones.