Auditoría de seguridad: FGC

Continuando con el desarrollo del proyecto que ya comenté en un post anterior, y basándome en una auditoría de seguridad hecha recientemente a una empresa pública de Madrid, he decidido publicar lo que he podido llegar a encontrar dedicando apenas un rato de mi tiempo libre.

Trasfondo

Como ya comenté en el post anterior, estoy intentando desarrollar una aplicación Open Source que permita a los usuarios de FGC disponer de una aplicación móvil más acorde con lo que considero que debería ser el servicio ofrecido, empezando entre otras cosas por la rapidez y el diseño de la misma.

Durante el desarrollo (y como usuario), evidentemente utilicé la aplicación oficial para ver qué podía incluir en mi proyecto, y había un par de funcionalidades que me parecieron interesantes, así que tiré del kit de decompilación para Android: dex2jar, apktool y jd.

Una vez tuve el código de la aplicación oficial en un formato legible, fui intentando comprenderlo para encontrar el lugar donde podría encontrar esa funcionalidad concreta.
Durante la lectura del código, fui apreciando que había bastantes URL hardcodeadas, y finalmente decidí ver qué podría llegar a sacar de ellas alguien que encontrara lo mismo que yo, pero tuviera peores intenciones.

Tras ver lo que pude encontrar en menos de media hora, paré de investigar.

Recorrido

Entre el código pueden encontrarse rutas hardcodeadas, que además incluyen una IP pública y algunas subrutas, como por ejemplo, esta:

IMAGEN URL EXPUESTA

Solo con abrir el enlace en un navegador muestra una ventana para descargar un archivo llamado fgcTarifes2014_3.sqlite, el cual es un archivo de 22MB que contiene todas las tarifas para este 2014.

DESCARGA

Esto quizás no es demasiado "jugoso", pero teniendo una ruta completa dentro del servidor, solo es necesario ir subiendo de directorio para encontrar más material expuesto.

Por ejemplo, teniendo en este caso la ruta http://xx.xx.xx.xx/FGC/fgc.sqlite, ¿qué pasaría si quitáramos el último elemento?.
Pues que nos encontraríamos con algo como esto:

DB EXPUESTA

Lo cual no nos dá mucha información a priori sobre qué es, pero dejando el campo vacío y pulsando en cualquiera de los botones...

INSERT

Madre mía, un formulario para hacer insert de datos en una tabla interna, accesible directamente sin autenticación... Y además, podemos ver la secuencia SQL completa.
Y viendo que en la captura anterior teníamos secciones como "routes", "stops"... no es muy difícil averiguar qué hace cada una.

Y finalmente, queda la ruta madre, acceder directamente a la IP a ver qué aparece.

La barrera

Accediendo a la IP, nos aparece un panel de autenticación sobre aspx:

AUTH

Por desgracia no disponemos de ningún user/pass para poder acceder, pero eso no impide que podamos ver el código fuente.

Nadamás abrirlo, podemos observar que el código fuente de la web está repleto de funciones JS:

SOURCE

Teniendo en cuenta que Google Chrome dispone de una consola javascript interactiva, sólo tenemos que hacer las modificaciones adecuadas para poder empezar a sacar algunos datos.

Podemos observar que en el JS hay una petición AJAX con el siguiente código:

$.ajax({
	type:"GET",
	url:"getMapa.aspx",
	data: param,
	success:function(datos){
		datosLoaded = datos;
		setTimeout("loadDatos()",150);
	}
});

Como podemos ver, esa petición requiere de una variable llamada param, que casualmente se forma justo encima de ese trozo de código:

var param = "fecha="+year+month+dia+"&filtre_hora_alerta="
+filtro_hores_alerta+"&filtre_hora_enviament="
+filtro_hores_enviament+"&filtre_tipologia="
+filtro_tipologies+"&filtre_linia="+filtro_linia
+"&filtre_estacio_sortida="+filtro_estacio_origen
+"&filtre_estacio_arribada="
+filtro_estacio_desti+"&ordre="+ordre+"&tipus_ordre="
+tipus_ordre;

Pero por desgracia, la variable se forma cada vez que se ejecuta una función, así que tendremos que forzar su creación a mano. Además, sería interesante saber qué contiene la respuesta de esa petición, así que solo necesitamos preparar el código para su ejecución en la consola.
Lo dejaremos tal que así:

var param = "fecha="+year+month+dia+"&filtre_hora_alerta="
+filtro_hores_alerta+"&filtre_hora_enviament="
+filtro_hores_enviament+"&filtre_tipologia="
+filtro_tipologies+"&filtre_linia="+filtro_linia
+"&filtre_estacio_sortida="+filtro_estacio_origen
+"&filtre_estacio_arribada="
+filtro_estacio_desti+"&ordre="+ordre+"&tipus_ordre="
+tipus_ordre;

$.ajax({
	type:"GET",
	url:"getMapa.aspx",
	data: param,
	success:function(datos){
		datosLoaded = datos;
        console.log(datos);
		setTimeout("loadDatos()",150);
	}
});

Con lo cual conseguiremos que una vez se ejecute la petición AJAX, nos muestre el resultado por la consola.
Ahora sí, ejecutamos el código.

Sorteando la barrera

Una vez tenemos la respuesta de la petición, vamos a echarle un ojo.

Sigue el siguiente esquema:

<div id="map" style="width:800px; height:480px;"></div>
<script type="text/javascript">
...
</script>

Como podemos ver, contiene un div con una id de "map", un ancho y un alto.
El código incluido dentro de las tag de script hace modificaciones sobre ese div, así que primero necesitaríamos tener ese div presente en el DOM.

Por suerte, Google Chrome tiene integrado un editor de DOM en vivo, así que solo necesitamos copiar la declaración del div y pegarla bajo el formulario de autenticación, tal que así:

EDITANDO EL DOM

Una vez tenemos el div insertado, solo tenemos que copiar todo el código contenido entre las dos tag de script, pegarlo en la consola de javascript de Chrome, ejecutarlo y comprobar el resultado:

MAPA DENUNCIAS

NOTA: He añadido un poco de estilo al mapa para centrarlo en la página

Si alguien ha utilizado la aplicación oficial de FGC reconocerá rápidamente el icono y el texto: FGC permite denunciar comportamientos incívicos desde su propia aplicación (ej: gente mendigando, presencia de viajeros sin billete...), así que acabamos de obtener, sin ningún tipo de nombre de usuario ni contraseña, ni ataque de ningún tipo, un mapa con las últimas denuncias realizadas por los usuarios, así como su localización.

Hasta aquí

Una vez comprobado lo sencillo que ha sido obtener esta cantidad de datos y recursos dejé de buscar, ni siquiera comprobé si había otros end-points en las URL del código fuente de la aplicación, porque esto ya me parecía suficientemente grave en lo que a la seguridad de una empresa pública respecta.

Al terminar, me puse en contacto con el autor de la auditoría hecha a BiciMad, quien me animó a publicarlo censurado, a ver si entre todos podemos crear una mayor concienciación sobre la seguridad, sobretodo en empresas públicas.

Además, antes de la publicación de este artículo se ha avisado por varias vías al personal de FGC sobre estos fallos para que puedan tomarse las medidas adecuadas.

EDIT: ACTUALIZACIÓN

A menos de 24h del envío del correo, la empresa ha "solucionado" el problema de la base de datos expuesta, haciendo que si se intenta acceder mediante la ruta antes descubierta, el resultado sea:

FORBIDDEN

Por mi parte no he recibido ni siquiera confirmación de que hayan leído lo que les envié, pero imagino que así lo han hecho, y se han dado cuenta de que no era demasiado bueno tener eso expuesto públicamente.

Solucionado? PUES NO

Con la conciencia más tranquila por haber avisado a la empresa y ver que se lo habían tomado un poco en serio, pensé que con el poco trabajo que me había llevado hacer esos pequeños hallazgos era muy improbable que no lo hubiera hecho otro ya antes.

Simplemente buscando una de las IP encontradas en Google me llevó hasta un script preparado para ejecutar cientos de denuncias falsas al servicio, lo cual eliminaría la utilidad de esa funcionalidad, ya que no se podrían distinguir las legítimas de las reales.

Pero la verdadera sorpresa ha llegado al buscar la otra: He encontrado el dominio asociado a la IP (es decir, un reverse DNS), el cual me ha llevado hasta la página web de la que, según creo, es la empresa autora de la aplicación móvil de FGC.

Sorprendido, simplemente he cambiado la IP por la URL de la empresa para ver como, ante mi, volvía a aparecer un panorama ya conocido:
Te suena?

Reflexión

Viendo como en apenas una semana se han encontrado fallos de seguridad graves en proyectos hechos a empresas públicas, realmente hace plantearse la tarea de búsqueda de empresas para realizar este tipo de servicios.

Según se cita en la auditoría hecha a BiciMad, el proyecto de la aplicación móvil fue:

Un proyecto enmarcado en el Lote 5 de la contratación de gestión de los servicios públicos de Madrid de 884 millones de euros en los próximos 12 años, con licitación a Bonopark S.L. de 25 millones de euros en 10 años

Con lo que estamos hablando de beneficios millonarios para hacer trabajos que son capaces de dejar a una infraestructura pública descubierta ante ataques de cualquier persona con un poco de conocimiente y muy malas intenciones.

Finalmente, y citando al autor original de la frase, Arasthel

Solo espero que con posts como este y muchísimos otros que hay con contenido similar (y realmente, poco contenido realmente técnico o complicado), algún día lo lea alguien de alguna empresa pública que tenga que contratar a una empresa para realizar algún proyecto similar, y se piense dos veces a qué empresa contrata, y se plantee si ese proyecto debe pasar por una auditoría de seguridad antes de ser lanzado (a no ser que quieran que un tercero se la haga, sean cual sean sus intenciones).