Asegurando las comunicaciones en Android

Con todas las violaciones de datos recientes, la privacidad se ha convertido en un tema importante. Casi todas las aplicaciones se comunican a través de la red, por lo que es importante considerar la seguridad de la información del usuario. En esta publicación, conocerá las mejores prácticas actuales para proteger las comunicaciones de su aplicación Android.

Utilizar HTTPS

A medida que desarrolla su aplicación, es una buena práctica limitar sus solicitudes de red a aquellas que son esenciales. Para los más importantes, asegúrese de que estén hechos a través de HTTPS en lugar de HTTP. HTTPS es un protocolo que encripta el tráfico para que no pueda ser interceptado fácilmente por los espías. Lo bueno de Android es que la migración es tan simple como cambiar la URL de http a https

URL url = new URL ("https://example.com"); HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection (); httpsURLConnection.connect ();

De hecho, las versiones de Android N y superiores pueden imponer HTTPS utilizando la configuración de seguridad de red de Android.

En Android Studio, seleccione la app / res / xml Directorio para su proyecto. Crear el xml Directorio si no existe ya. Selecciónelo y haga clic. Archivo> Nuevo archivo. Llámalo network_security_config.xml. El formato para el archivo es el siguiente:

   example.com  

Para indicar a Android que use este archivo, agregue el nombre del archivo a la etiqueta de la aplicación en la AndroidManifest.xml expediente:

Actualizar proveedores criptográficos

El protocolo HTTPS ha sido explotado varias veces a lo largo de los años. Cuando los investigadores de seguridad reportan vulnerabilidades, los defectos suelen ser parcheados. La aplicación de los parches garantiza que las conexiones de red de su aplicación estén utilizando los protocolos estándar de la industria más actualizados. Las versiones más recientes de los protocolos contienen menos debilidades que las anteriores.. 

Para actualizar los proveedores criptográficos, deberá incluir los servicios de Google Play. En su archivo de módulo de build.gradle, agregue la siguiente línea a la sección de dependencias:

implementación 'com.google.android.gms: play-services-safetynet: 15.0.1'

La API de servicios de SafetyNet tiene muchas más funciones, incluida la API de navegación segura que comprueba las URL para ver si han sido marcadas como una amenaza conocida, y una API reCAPTCHA para proteger su aplicación de spammers y otro tráfico malicioso.

Después de sincronizar Gradle, puedes llamar al ProveedorInstaladores installIfNeededAsync método:

la clase pública MainActivity extiende la actividad Implementa ProviderInstaller.ProviderInstallListener @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); ProviderInstaller.installIfNeededAsync (this, this); 

los onProviderInstalled () Se llama al método cuando el proveedor se actualiza correctamente o ya está actualizado. De otra manera, onProviderInstallFailed (int errorCode, Intent recoveryIntent) se llama. 

Certificado y establecimiento de claves públicas

Cuando realiza una conexión HTTPS a un servidor, el servidor presenta un certificado digital y lo valida Android para asegurarse de que la conexión sea segura. El certificado puede firmarse con un certificado de una autoridad de certificación intermedia. Este certificado utilizado por la autoridad intermedia puede a su vez estar firmado por otra autoridad intermedia, y así sucesivamente, que es confiable siempre que el último certificado esté firmado por una autoridad de certificación raíz que ya sea confiable para el sistema operativo Android..

Si alguno de los certificados en la cadena de confianza no es válido, entonces la conexión no es segura. Si bien este es un buen sistema, no es infalible. Es posible que un atacante indique al sistema operativo Android que acepte certificados personalizados. Los proxies de intercepción pueden poseer un certificado de confianza, y si el dispositivo está controlado por una empresa, es posible que la empresa haya configurado el dispositivo para que acepte su propio certificado. Estos escenarios permiten un ataque "man in the middle", que permite descifrar y leer el tráfico HTTPS. 

La fijación de certificados llega al rescate al verificar el certificado del servidor que se presenta contra una copia del certificado esperado. Esto evita que se realicen conexiones cuando el certificado es diferente del esperado.

Para implementar el anclaje en Android N y superior, debe agregar un hash (llamado alfileres) del certificado en el network_security_config.xml expediente. Aquí hay una implementación de ejemplo:

   duckduckgo.com  lFL47 + i9MZkLqDTjnbPTx2GZbGmRfvF3GkEh + J + 1F3g = w9MWhhnFZDSPWTFBjaoeGuClsrCs7Z70lG7YNlo8t + s =   

Para encontrar los pines de un sitio específico, puede ir a SSL Labs, ingresar al sitio y hacer clic en Enviar. O, si está desarrollando una aplicación para una empresa, puede solicitarla a la empresa..

Nota: si necesita admitir dispositivos que ejecuten una versión de SO anterior a Android N, puede usar la biblioteca TrustKit. Utiliza el archivo de configuración de seguridad de red exactamente de la misma manera.

Desinfección y Validación

Con todas las protecciones hasta ahora, sus conexiones deben ser bastante seguras. Aun así, no te olvides de la validación de programación regular. Los datos confiados a ciegas recibidos de la red no son seguros. Una buena práctica de programación es el "diseño por contrato", donde las entradas y salidas de sus métodos satisfacen un contrato que define expectativas de interfaz específicas. 

Por ejemplo, si su servidor espera una cadena de 48 caracteres o menos, asegúrese de que la interfaz solo devolverá hasta 48 caracteres inclusive..

if (editText.getText (). toString (). length () <= 48)  ; //return something…  else  ; //return default or error 

Si solo está esperando números del servidor, sus entradas deben verificar esto. Si bien esto ayuda a prevenir errores inocentes, también reduce la probabilidad de ataques de corrupción de memoria e inyección. Esto es especialmente cierto cuando esos datos se pasan a NDK o código C y C ++ nativo de JNI.

Lo mismo ocurre con el envío de datos al servidor. No envíe datos a ciegas, especialmente si son generados por el usuario. Por ejemplo, es una buena práctica limitar la duración de la entrada del usuario, especialmente si será ejecutada por un servidor SQL o cualquier tecnología que ejecutará código. 

Si bien proteger a un servidor contra ataques está fuera del alcance de este artículo, como desarrollador móvil, puede hacer su parte eliminando los caracteres del idioma que usa el servidor. De esa manera, la entrada no es susceptible a ataques de inyección. Algunos ejemplos son quitar comillas, puntos y comas y barras cuando no son esenciales para la entrada del usuario:

string = string.replace ("\\", "") .replace (";", "") .replace ("\" "," ") .replace (" \ '"," ");

Si sabe exactamente el formato que se espera, debe verificarlo. Un buen ejemplo es la validación de correo electrónico:

privado final String emailRegexString = "^ [A-Za-z0-9 ._% + \\ -] + @ [A-Za-z0-9. \\ -] + \\. [A-Za-z]  2,4 $ "; privado booleano isValidEmailString (String emailString) return emailString! = null && Pattern.compile (emailRegexString) .matcher (emailString) .matches (); 

Los archivos pueden ser revisados ​​también. Si está enviando una foto a su servidor, puede verificar que sea una foto válida. Los dos primeros bytes y los dos últimos bytes son siempre FF D8 y FF D9 para el formato JPEG.

el booleano estático privado isValidJPEGAtPath (String pathString) lanza IOException RandomAccessFile randomAccessFile = null; intente randomAccessFile = new RandomAccessFile (pathString, "r"); long length = randomAccessFile.length (); si < 10L)  return false;  byte[] start = new byte[2]; randomAccessFile.readFully(start); randomAccessFile.seek(length - 2); byte[] end = new byte[2]; randomAccessFile.readFully(end); return start[0] == -1 && start[1] == -40 && end[0] == -1 && end[1] == -39;  finally  if (randomAccessFile != null)  randomAccessFile.close();   

Tenga cuidado al mostrar una alerta de error que muestre directamente un mensaje del servidor. Los mensajes de error pueden revelar información privada de depuración o relacionada con la seguridad. La solución es hacer que el servidor envíe un código de error que el cliente busca para mostrar un mensaje predefinido.

Comunicación con otras aplicaciones

Mientras protege la comunicación hacia y desde el dispositivo, también es importante proteger IPC. Ha habido casos en los que los desarrolladores han dejado archivos compartidos o han implementado sockets para intercambiar información confidencial. Esto no es seguro. Es mejor usar Intencións. Puede enviar datos utilizando un Intención proporcionando el nombre del paquete como este:

Intención intención = nueva intención (); intent.setComponent (nuevo ComponentName ("com.example.app", "com.example.app.TheActivity")); intent.putExtra ("UserInfo", "Cadena de ejemplo"); startActivity (intención);

Para transmitir datos a más de una aplicación, debe hacer cumplir que solo las aplicaciones firmadas con su clave de firma obtendrán los datos. De lo contrario, la información que envíe puede ser leída por cualquier aplicación que se registre para recibir la transmisión. Del mismo modo, una aplicación maliciosa puede enviar una transmisión a su aplicación si se ha registrado para recibir la transmisión. Puede utilizar un permiso al enviar y recibir transmisiones donde firma se utiliza como el nivel de protección. Puede definir un permiso personalizado en el archivo de manifiesto como este:

 

Entonces puedes otorgar el permiso así: 

Ambas aplicaciones necesitan tener los permisos en el archivo de manifiesto para que funcione. Para enviar la transmisión:

Intención intención = nueva intención (); intent.putExtra ("UserInfo", "Cadena de ejemplo"); intent.setAction ("com.example.SOME_NOTIFICATION"); sendBroadcast (intención, "com.example.mypermission");

Alternativamente, puedes usar setPackage (String) al enviar una transmisión para restringirla a un conjunto de aplicaciones que coinciden con el paquete especificado. Ajuste Android: exportado a falso en el archivo de manifiesto se excluirán las transmisiones que se reciban desde fuera de su aplicación.

Encriptado de fin a fin

Es importante comprender los límites de HTTPS para proteger las comunicaciones de red. En la mayoría de las implementaciones de HTTPS, el cifrado termina en el servidor. Por ejemplo, su conexión al servidor de una corporación puede ser a través de HTTPS, pero una vez que el tráfico llega al servidor, no está encriptado. Luego se puede reenviar a otros servidores, ya sea estableciendo otra sesión HTTPS o enviándola sin cifrar. La corporación puede ver la información que se ha enviado y, en la mayoría de los casos, es un requisito para las operaciones comerciales. Sin embargo, también significa que la empresa podría pasar la información a terceros sin cifrar..

Hay una tendencia reciente llamada "cifrado de extremo a extremo" en la que solo los dos dispositivos de comunicación finales pueden leer el tráfico. Un buen ejemplo es una aplicación de chat encriptada donde dos dispositivos móviles se comunican entre sí a través de un servidor; Solo el remitente y el receptor pueden leer los mensajes de cada uno..

Una analogía para ayudarlo a comprender el cifrado de extremo a extremo es imaginar que desea que alguien le envíe un mensaje que solo usted puede leer. Para hacer esto, les proporciona una caja con un candado abierto (la clave pública) mientras mantiene la llave del candado (clave privada). El usuario escribe un mensaje, lo coloca en el cuadro, bloquea el candado y se lo envía a usted. Solo tú puedes leer el mensaje porque eres el único con la llave para desbloquear el candado.

Con el cifrado de extremo a extremo, ambos usuarios se envían mutuamente sus claves. El servidor solo proporciona un servicio para la comunicación, pero no puede leer el contenido de la comunicación. Si bien los detalles de la implementación están fuera del alcance de este artículo, es una tecnología poderosa. Si desea obtener más información sobre este enfoque, un buen lugar para comenzar es el repositorio de GitHub para el proyecto Signal de código abierto..

Conclusión

Con todas las nuevas leyes de privacidad como GDPR, la seguridad es cada vez más importante. A menudo es un aspecto descuidado en el desarrollo de aplicaciones móviles..

En este tutorial, ha cubierto las mejores prácticas de seguridad, que incluyen el uso de HTTPS, el establecimiento de certificados, el saneamiento de datos y el cifrado de extremo a extremo. Estas mejores prácticas deben servir como base para la seguridad al desarrollar su aplicación móvil. Si tiene alguna pregunta, no dude en dejarla a continuación, y mientras esté aquí, consulte algunos de mis otros tutoriales sobre la seguridad de la aplicación Android.!