OAuth 2.0, autorizando el uso de recursos

I’ve translated this post in my new site, you can find it under Brief introduction to OAuth Authorization Framework.

OAuth 2.0 tal y como se define en el RFC 6749 es aquél framework de autorización que permite a la aplicación de un tercero obtener un acceso limitado a un cierto servicio http, lo que comúnmente llamamos un API.

El framework de autorización OAuth, establece un conjunto de roles entre los que se deben orquestar los procesos necesarios para establecer si finalmente un cliente tiene los permisos para acceder a un recurso.

Los roles definidos son el cliente que consume un recurso, el servidor donde se halla este recurso, el dueño del recurso que va a ser consumido y aquel servidor que autoriza el consumo del recurso.

Roles en OAuth

En un ejemplo típico, el cliente podría ser aquella web a la que accedo y en lugar de crear una nueva cuenta me permite usar mi credencial de Facebook. El servidor del recurso puede ser Facebook también. El dueño del recurso sería yo mismo.  Y por último el servidor de autorización sería el de facebook.com.

¿Cómo se establece el diálogo entre los distintos actores para finalmente autorizar el uso a un cierto cliente?

La web a la que accedo va a pedir al dueño del recurso, en el ejemplo sería yo mismo, autorización para usar la información. En este paso normalmente se determina el nivel de autorización, si sólo voy a permitir el acceso en mi nombre, o si permito que se acceda a más información de mi perfil. Si concedo permiso a utilizar mis credenciales, al final la aplicación cliente va a presentar un token de acceso al servidor del recurso para que pueda acceder a esta novedosa web.

Es importante notar la presencia de un token de autorización, este token puede ser almacenado por la aplicación cliente y ahorrar al usuario final ( que podría ser una aplicación ) de tener que hacer login cada vez que quiera acceder ( usaría el login de facebook. Simplificamos el proceso de registro, a cambio de hacer concesiones a un tercero.

Advertisements

¿Cómo de privada debe ser mi API?

Tal y como entiendo, los datos públicos (opendata) deberían ser expuestos mediante APIs públicas de forma que estén disponibles para los ciudadanos, y todo aquel que quiera utilizarlos.

En el caso de las empresas, dependerá de su modelo de negocio, de hecho exponer servicios con acceso directo a los objetos de negocio debería hacerse en distintos niveles, que tal y como yo veo podrían ser los siguientes:

  • Por ejemplo, en un cierto nivel sólo aquella información que quiera suministrarse de forma pública, API pública, estaría disponible para la comunidad global de forma que pueda se expanda el conocimiento de productos y servicios de la compañía, u otras informaciones que la compañía deba exponer por algún marco regulatorio. Este API sería de acceso público con libre acceso y registro a la comunidad, o con acceso restringido a una gran comunidad de clientes.
  • Avanzando en cuanto a privacidad, habrá otros modelos del datos de la compañía que estarán restringidos para intercambio con otras empresas (lo que se denomina business to business – b2b ). De esta forma las aplicaciones de terceros que consuman las APIs privadas formarán parte de una o más comunidades privadas a las que deberíamos ofrecer distintas APIs dependiendo del escenario, por ejemplo intercambio de información de pagos y cobros, de pedidos y facturas, movimientos de almacén, etc. Estas son las comúnmente llamadas APIs privadas.
  • Y en el último nivel de restricción, habrá APIs de uso interno, lo cual no quiere decir que sean APIs que se puedan consumir internamente a discreción, si no que su existencia implica también un gobierno sobre su ciclo de vida, notificación a los consumidores de nuevas versiones o cambios, y control del consumo del API y de las condiciones del servicio por parte de los distintos consumidores. Estos consumidores internos pueden perfectamente ser otros sistemas, lo que tradicionalmente se llama integración application to application – A2A. Yo llamo a estas APIs internas, aunque muchas veces son APIs propietarias de los componentes software que la compañía utilice, SCM, CRP, CRM, HR, ERP.

Esta gestión de los diferentes niveles de privacidad de la información, y por tanto de las diferentes APIs que se utilizan, implica todo un proceso de gobierno del ciclo de vida de las distintas APIs, control de los cambios, y adicionalmente la gestión de la Autenticación de los consumidores, el control de la Autorización de uso del recurso que se pretende acceder y por su puesto la Auditoría de las operaciones realizadas lo cual no es muy diferente de los requisitos que pedimos a un API pública.

La era de las APIs públicas

Después de describir las Web APIs en mi anterior post, deje pendiente por analizar distintas visiones que están teniendo lugar en el espacio de las APIs, principalmente en la dicotomía APIs publicas / APIs privadas.

Definía un Web API, no solo cómo el conjunto de funciones y procedimientos que permiten manejar los objetos de negocio, sino además todos aquellos otros elementos alrededor del API en sí misma que permiten su gobierno, el control de los accesos y la seguridad en sí misma sobre dichas funciones y procedimientos.

Por extensión de un Web API, un Web API pública es aquella Web API que expone los objetos de negocio a la comunidad de desarrolladores de internet, es decir, potencialmente a toda la comunidad de desarrolladores.

Habitualmente es necesaria una gestión de esta comunidad de desarrolladores de forma que se tenga un gobierno de los diferentes desarrolladores, así como las apps o mashups que desarrollan, en definitiva de los clientes de nuestra API pública. De esta forma podemos saber cuáles son los usos más comunes, y así progresar el desarrollo de nuevas versiones teniendo en consideración esos usos.

Una API pública puede ser usada por cualquiera para acceder a los métodos de los objetos internos de negocio, solo debe tener un token de identificación de desarrollador, lo cual dependiendo del negocio en sí mismo puede crear un conflicto, ya que como veremos a continuación lo genial de las Web APIs, permitir que unos sitios web usen recursos de otros y ambos crezcan juntos, también ha desembocado en algunos desencuentros.

Twitter tuvo que cambiar su API pública para que la existencia de aplicaciones de terceros no afectasen a su modelo de negocio.

Netflix ha anunciado que va a retirar su API pública, y solamente un conjunto de desarrolladores que realmente estén aportando valor a su negocio van a tener acceso a la nueva versión del API, que será privada. Veremos más sobre APIs privadas en un próximo post.

Aunque aparentemente podría parecer que exponer un API pública podría ser sólo fuente de desencuentros, es también una gran fuente de ventajas. Es el caso de American Express, que expone un API pública para la realización de pagos con puntos de su programa de fidelización (Amex Points), un uso insospechado para American Express de esta API era la posibilidad de pagar con Amex Points en la archiconocida Uber con el incremento en el número potencial de pagos a través de este API pública.

La discusión es si las APIs públicas están en vías de desaparecer, y estamos en el fin de una era, o si se impone un cambio de modelo. Seguiré ahondando en esto en el próximo post.

Seguridad en las APIs – El caso snapchat

En esta economía globalizada que nos ocupa, y a veces nos preocupa, uno de los elementos en los que más se trabaja es en la construcción de una marca, la publicidad, el marketing, y como no la construcción de un producto. Un gran esfuerzo que muchas veces es tirado por tierra por un error que cause un gran impacto mediático.

Habitualmente cuando hablamos de productos que involucran un API, este impacto mediático suele venir por un problema de seguridad en esta API. Datos robados, información de usuarios desvelada, seguridad comprometida, caída del servicio, son algunos ejemplos de algo sobre lo que estamos acostumbrándonos a escuchar.

En el último año snapchat, el whatsapp americano, nos está proporcionando una fuente inagotable de noticias, y habitualmente desagradables.

Primero fueron advertidos por parte de la comunidad de que el diseño de su API podría causar fugas de información, dicho y hecho al pasar de los meses los números de teléfono de sus usuarios fueron extraídos usando su API, y un porqué no decirlo una infinita paciencia para descargar tanta información.

¿Es esto tan difícil de proteger? Situar una capa de seguridad por delante de la capa de negocio, que preventa la salida de información confidencial, grandes cantidades de información no es una tarea complicada con un API Gateway. 4,6 millones de usuarios a mi me parece un numero suficientemente elevado como para tomarlo en cuenta.

Aparentemente filtrar los números de teléfono de todos los usuarios de un servicio no parecía algo suficientemente jugoso, con lo que nos hemos desayunado con otro fallo de seguridad, esta vez algo más picante.

16 Gb de fotos intimas de miles de personas anónimas (200.000) puestas a disposición de todo aquel que tenga un poco de curiosidad.

Lo curioso es que desde snapchat sólo echan balones fuera, cuestión que si no fuera por su trayectoria, sería más creible.

En este caso, el problema parece la gestión de los accesos al API, que posiblemente no se estaba realizando de una forma suficientemente segura. ¿Seguiremos relacionando esta marca con fallos de seguridad, esperemos que no?

¿Qué es un Web API?

I’ve translated this post in my new site, you can find it under What’s a REST API?.
Siempre que veo algún tipo de presentación, demo, evento o similar relativo a las Web APIs en todas las ocasiones se define un API (Application Programming Interface) como aquél conjunto de funciones y procedimientos que ofrece cierta biblioteca para ser utilizado por otro software como una capa de abstracción (fuente wikipedia ).

Lo cual está muy bien, pero solamente define una parte de lo que actualmente entendemos como API, además de todas las implicaciones del término API actualmente. Por ello yo lo tiendo a llamar Web APIs.

Un Web API REST, es un conjunto de funciones y procedimientos de creación, consulta, actualización y borrado (CRUD – Crear, leer, actualizar y borrar) sobre objetos de negocio. De esta forma se expone el objeto de negocio sobre una cierta url (http://example.com/v1/user) y con distintos métodos ( PUT – Crear, GET – Leer, PUT – Actualizar, DELETE – Borrar) se opera sobre estos objetos de negocio. Habitualmente este conjunto de funciones se exponen fuera de la compañía para permitir ciertas operaciones de B2B, lo que dicho de otra forma no es más que facilitar el acceso a los servicios de la compañía para las empresas con las que la nuestra hace negocio.

Con el boom de la Web 2.0 más y más sitios ofrecen un API que permite realizar ciertas funciones o procedimientos. Por ejemplo tomando el API de Twitter, se pueden publicar tweets, y extraer informaciones como tweets filtrados por ciertos parámetros, o incluso estadísticas. Lo cual ha permitido la creación de más negocio sobre estos servicios (APIs), en sitios que integran Twitter, Facebook, Linkedin,y otras redes sociales para poder hacer seguimiento por ejemplo de campañas publicitarias.

Entre las preocupaciones de exponer estos objetos de negocio a terceros, están saber cómo debo dimensionar mis sistemas para dar cabida a esta nueva vía de negocio, cuál de mis interlocutores de negocio hace más uso del API, medir este uso, ¿cómo autorizo a los usuarios de mi plataforma a consultar, crear, modificar y borrar desde la plataforma de un tercero?, y sobretodo prevenir que haya accesos no autorizados, ni extracción de información confidencial (ya sea por un interlocutor de negocio, o por un hacker de la competencia).

Sobre la base de las preocupaciones más básicas comentadas, se han ido desarrollando mecanismos para la identificación de consumidores mediante tokens, herramientas de monitorización y reporting automático sobre esta monitorización, mecanismos de autenticación ( OpenID ) y autorización ( OAuth ), y mecanismos para definir distintas políticas de seguridad sobre las APIs expuestas.

No obstante este modelo, ni está presente en todas las compañías, ni creo que sea el modelo idóneo en los próximos años. En los próximos posts pretendo hacer una distinción entre este modelo de acceso directo a los datos, y otros modelos en los por ejemplo que se distingue entre un API pública (public API) y otras APIs privadas (prívate APIs).

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.

 

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.