La Capa de Sockets seguros (SSL), ahora técnicamente conocida como Transport Layer Security(TLS), es un bloque de construcción común para las comunicaciones cifradas entre clientes y servidores. Es posible que una aplicación pueda usar SSL incorrectamente, de modo que las entidades maliciosas puedan interceptar los datos de una aplicación a través de la red., Para ayudarle a asegurarse de que esto no suceda en su aplicación, este artículo destaca las dificultades comunes al usar protocolos de red seguros y aborda algunas preocupaciones más importantes sobre el uso de infraestructura de Clave Pública (PKI).
también debe leer AndroidSecurity Overview, así como PermissionsOverview.
conceptos
en un escenario de uso típico de SSL, un servidor se configura con un certificado que contiene una clave pública, así como una clave privada coincidente., Como parte del apretón de manos entre un cliente SSL y un servidor, el servidor demuestra que tiene la Clave Privada firmando su certificado con criptografía de Clave Pública.
sin embargo, cualquiera puede generar su propio certificado y clave privada, por lo que un simple apretón de manos no prueba nada sobre el servidor excepto que el servidor conoce la clave privada que coincide con la Clave Pública del certificado. Una forma de resolver este problema es hacer que el cliente tenga un conjunto de uno o más certificados en los que confía. Si el certificado no está en el conjunto, el servidor no es de confianza.,
Hay varias desventajas de este enfoque simple. Los servidores deberían poder pasar a claves más fuertes con el tiempo («rotación de claves»), que reemplaza la Clave Pública en el certificado por una nueva. Desafortunadamente, ahora la aplicación cliente tiene que ser actualizada debido a lo que es esencialmente un cambio de configuración del servidor. Esto es especialmente problemático si el servidor no está bajo el control del desarrollador de la aplicación, por ejemplo, si es un servicio web de terceros. Este enfoque también tiene problemas si la aplicación tiene que hablar con servidores arbitrarios, como un navegador web o una aplicación de correo electrónico.,
para abordar estas desventajas, los servidores se configuran típicamente con certificados de emisores conocidos llamados autoridades de certificación (CA).La plataforma host generalmente contiene una lista de CA bien conocidas que trusts.As de Android 4.2 (Jelly Bean), Android actualmente contiene más de 100 CA que se actualizan en cada versión. Al igual que un servidor, una CA tiene un certificado y una clave privada. Al emitir un certificado para un servidor, la CA firma el certificado del servidor usando su Clave Privada. Theclient puede verificar que el servidor tiene un certificado emitido por una CA conocida por la plataforma.,
sin embargo, mientras se resuelven algunos problemas, el uso de CAs introduce otro. Debido a que la CA emite certificados para muchos servidores, todavía necesita alguna forma de asegurarse de que está hablando con el servidor que desea. Para resolver esto, el certificado emitido por la CA identifica al servereither con un nombre específico como gmail.com o un conjunto salvaje de hosts como *.google.com.
el siguiente ejemplo hará que estos conceptos sean un poco más concretos., En el fragmento debajo de una línea de comandos, el comando openssl
de la herramienta s_client
mira la información del certificado del servidor de Wikipedia. Especifica el puerto 443 porque es el predeterminado para HTTPS. El comando envía la salida de openssl s_client
a openssl x509
, que formatea la información sobre certificados de acuerdo con el estándar X. 509. Específicamente, el comando solicita el asunto, que contiene la información del nombre del servidor, y el emisor, que identifica la CA.,
Puede ver que el certificado se emitió para los servidores que coinciden con *.wikipedia.org bythe RapidSSL CA.
un ejemplo HTTPS
suponiendo que tenga un servidor web con certificado emitido por una CA conocida, puede hacer una solicitud segura con Code assimple esto:
sí, realmente puede ser así de simple. Si desea adaptar la solicitud HTTP, puede enviar toan HttpURLConnection
., La documentación de Android paraHttpURLConnection
tiene más ejemplos sobre cómo tratar los encabezados de solicitud y respuesta, publicar contenido, administrar cookies, usar proxies,almacenar respuestas en caché, etc. Pero en términos de los detalles para verificar certificados y nombres de host, Androidframework se encarga de ello por usted a través de estas API.Aquí es donde quieres estar si es posible. Dicho esto, a continuación se presentan algunas otras consideraciones.,
problemas comunes al verificar certificados de servidor
supongamos que en lugar de recibir el contenido de getInputStream()
, arroja una excepción:
esto puede suceder por varias razones, incluyendo:
- LA CA que emitió el certificado de servidor era desconocida
- El certificado de servidor no estaba firmado por una CA, pero sí estaba firmado por sí mismo
- la configuración del servidor ca
en las siguientes secciones se explica cómo solucionar estos problemas mientras se mantiene segura la conexión con el servidor.,
Autoridad de certificación desconocida
en este caso, se produce SSLHandshakeException
porque tiene una CA en la que el sistema no confía. Podría deberse a que tienes un certificado de una CA nueva en la que Android aún no confía o a que tu app está funcionando en una versión anterior sin la CA. Más a menudo, una CA se desconoce porque no es una CA pública, sino una privada emitida por una organización como un gobierno,una corporación o una institución educativa para su propio uso.
afortunadamente, puede enseñar HttpsURLConnection
a confiar en un conjunto específico de CA., El procedimiento puede ser un poco complicado, por lo que a continuación se muestra un ejemplo que toma una CA específica de InputStream
, la usa para crear un KeyStore
,que luego se usa para crear e inicializar unTrustManager
. A TrustManager
es lo que el sistema utiliza para validar certificados del servidor y-creando uno a partir de un KeyStore
con una o más CAs-estas serán las únicas CAs en las que TrustManager
.,
Dada la nueva TrustManager
,el ejemplo inicializa una nueva SSLContext
que providesan SSLSocketFactory
puede utilizar para reemplazar el valor predeterminadoSSLSocketFactory
deHttpsURLConnection
. De esta manera theconnection utilizará sus CA para la validación del certificado.
Aquí está el ejemplo infull usando una CA organizacional de la Universidad de Washington:
con un ID
que conoce sus CA,el sistema puede validar que su certificado de servidor proviene de un emisor de confianza.,
precaución: muchos sitios web describen una solución alternativa pobre que es instalar un TrustManager
que no hace nada. Si hace esto, también podría no cifrar su comunicación, porque cualquiera puede atacar a sus usuarios en un punto de acceso Wi-Fi público utilizando trucos de DNS para enviar el tráfico de sus usuarios a través de un proxy propio que pretende ser su servidor. El atacante puede entonces registrar contraseñas y otros datos personales., Esto funciona porque el atacante puede generar un certificado y-sin un TrustManager
que valide que el certificado proviene de un trustedsource-su aplicación podría estar hablando con cualquier persona. Así que no hagas esto, ni siquiera temporalmente. Siempre puede hacer que su aplicación confíe en el emisor del certificado del servidor, así que simplemente hágalo.
certificado de servidor autofirmado
el segundo caso de SSLHandshakeException
se debe a un certificado autofirmado, lo que significa que el servidor se comporta como su propia CA.,Esto es similar a una Autoridad de certificación desconocida, por lo que puede usar el mismo enfoque de la sección anterior.
Puede crear su propio TrustManager
, esta vez confiando directamente en el certificado del servidor. Esto tiene todas las desventajas discutidas anteriormente de vincular su aplicación directamente a un certificado, pero se puede hacer de forma segura. Sin embargo, debe tener cuidado de asegurarse de que su certificado autofirmado tenga una clave razonablemente fuerte. A partir de 2012, una firma RSA de 2048 bits con un exponente de 65537 que expira al año es aceptable., Al girar las teclas, debe verificar si hay recomendaciones de una autoridad (como NIST) sobre lo que es aceptable.
falta Autoridad de certificación intermedia
el tercer caso de SSLHandshakeException
se produce debido a la falta de una CA intermedia. La mayoría de las publicCAs no firman certificados de servidor directamente. En su lugar, utilizan su certificado de CA principal,denominado CA raíz, para firmar CA intermedias. Hacen esto para que la CA raíz pueda almacenarse en línea para reducir el riesgo de compromiso., Sin embargo, los sistemas operativos como Android typicallytrust solo raíz CA directamente,lo que deja un corto espacio de confianza entre el servercertificate—firmado por la CA intermedia—y el verificador de certificados, que conoce la CA raíz. Para resolverlo, el servidor no envía al cliente solo su certificado durante el handshake SSL, sino una cadena de certificados desde la CA del servidor a través de cualquier intermediario necesario para llegar a la CA raíz de confianza.
para ver cómo se ve esto en la práctica, aquí está el correo.Google.,com certificatechain visto por el comando openssl
s_client
:
esto muestra que el servidor envía un certificado por correo.Google.emitido por la CA Thawte SGC, que es una CA intermedia, y un segundo certificado para la CA Thawte SGC emitido por una CA Verisign, que es la CA primaria que es confiable por Android.
sin embargo, no es raro configurar un servidor para que no incluya la CA intermedia necesaria., Por ejemplo, aquí hay un servidor que puede causar un error en los navegadores Android yexcepciones en las aplicaciones Android:
lo que es interesante notar aquí es que visitar este servidor en la mayoría de los navegadores de escritorio no causa un error como una CA completamente desconocida o un certificado de servidor autofirmado. Esto se debe a que la mayoría de los navegadores de escritorio almacenan en caché CAs intermedias de confianza a lo largo del tiempo. Una vez que un navegador ha visitado y se ha enterado de una CA intermedia de un sitio, no necesitará tener la CA intermedia incluida en la cadena de certificados la próxima vez.,
algunos sitios hacen esto intencionalmente para servidores web secundarios utilizados para servir Recursos. Por ejemplo, pueden tener su página HTML principal servida por un servidor con una cadena de certificación completa, pero tienen servidores para recursos como imágenes, CSS o JavaScript que no incluyen theCA, presumiblemente para ahorrar ancho de banda. Desafortunadamente, a veces estos servidores pueden estar proporcionando un servicio web que está tratando de llamar desde su aplicación de Android, que no es tan indulgente.
Hay dos enfoques para resolver este problema:
- configurar el servidor para incluir la CA intermedia en la cadena de servidores., La mayoría de las Ca proporcionan documentación sobre cómo hacer esto para todos los servidores web comunes. Este es el único enfoque si necesita que el sitio funcione con navegadores Android predeterminados al menos a través de Android 4.2.
- O, trate la CA intermedia como cualquier otra CA desconocida, y cree un
TrustManager
para confiar en ella directamente, como se hizo en las dos secciones anteriores.
problemas comunes con la verificación de nombres de host
como se mencionó al principio de este artículo,hay dos partes clave para verificar una conexión SSL., El primero que debe verificar el certificado es de una fuente de confianza, que fue el foco de la sección anterior. El enfoque de esta sección es la segunda parte: asegurarse de que el servidor al que está hablando presente el certificado correcto. Cuando no lo hace, normalmente verá un error como este:
una de las razones por las que esto puede suceder es debido a un error de configuración del servidor. El servidor está configurado con un certificado que no tiene un asunto o campos de nombre alternativo de asunto que coincidan con el servidor al que está tratando de llegar. Es posible utilizar un certificado con muchos servidores diferentes., Por ejemplo, mirando la google.com Certificado conopenssl
s_client -connect google.com:443 | openssl x509 -text
puede ver que un sujeto admite *.google.com pero también nombres alternativos de Sujetos para *.youtube.com,*. android.com, y otros. El error solo se produce cuando el nombre de servidor al que se está conectando no aparece en el certificado como aceptable.
desafortunadamente esto también puede suceder por otra razón: alojamiento virtual. Cuando se comparte un servidor para más de un nombre de host con HTTP, el servidor web puede decir a partir de la solicitud HTTP / 1.1 Cuál es el nombre de host de destino que el cliente está buscando., Desafortunadamente esto es complicado con https, porque el servidor tiene que saber qué certificado devolver antes de ver el HTTPrequest. Para abordar este problema, las versiones más recientes de SSL, Específicamente TLSv.1.0 y versiones posteriores,soporta Server Name Indication (SNI), que permite al cliente SSL especificar el intendedhostname al servidor para que se pueda devolver el certificado adecuado.
afortunadamente, HttpsURLConnection
supportsSNI desde Android 2.3. Un workaroundif que necesita para apoyar Android 2.,2 (y anterior) es configurar un host alternativo en un puerto único para que sea inequívoco Qué certificado de servidor devolver.
la alternativa más drástica es reemplazar HostnameVerifier
por uno que no use el nombre de host de su host virtual, sino el devuelto por el servidor por defecto.
precaución: reemplazar HostnameVerifier
puede ser muy peligroso si el otro host virtual no está bajo su control, porque anon-pathattacker podría dirigir el tráfico a otro servidor sin su conocimiento.,
si todavía está seguro de que desea anular la verificación del nombre de host, aquí hay un ejemplo que reemplaza el Verificador para un solo URLConnection
con uno que aún verifica que el nombre de host está al menos en esperado por la aplicación:
pero recuerde, si se encuentra reemplazando la verificación del nombre de host, especialmente debido al alojamiento virtual, sigue siendo muy peligroso si el otro host virtual no está bajo su control y debe encontrar una alternativa alojamiento arrangementthat evita este problema.,
Advertencias sobre el uso directo de SSLSocket
hasta ahora, los ejemplos se han centrado en HTTPS utilizando HttpsURLConnection
.A veces, las aplicaciones necesitan usar SSL por separado de HTTP. Por ejemplo, una aplicación de correo electrónico puede usar variantes SSL de SMTP, POP3 o IMAP. En esos casos, la aplicación querría usar SSLSocket
directamente, de la misma manera que HttpsURLConnection
lo hace internamente.
las técnicas descritas en sofar para tratar los problemas de verificación de certificados también se aplican a SSLSocket
.,De hecho, cuando se utiliza un custom TrustManager
, lo que se pasa aHttpsURLConnection
es un SSLSocketFactory
.Así que si usted necesita usar un TrustManager
con unSSLSocket
, followthe mismos pasos y el uso que de SSLSocketFactory
para crear suSSLSocket
.
precaución: SSLSocket
no realiza la verificación del nombre de host. Le corresponde a su aplicación hacer su propia verificación de nombre de host, preferiblemente llamando a getDefaultHostnameVerifier()
con el nombre de host esperado., Además, HostnameVerifier.verify()
no genera una excepción por error, sino que devuelve un resultado booleano que debe verificar explícitamente.
Aquí hay un ejemplo que muestra cómo puede hacer esto. Muestra que al conectar togmail.com puerto 443 sin soporte SNI, recibirá un certificado formail.google.com. esto se espera en este caso, así que compruebe para asegurarse de que el certificado es de hecho para mail.google.com:
Denylisting
SSL depende en gran medida de las CA para emitir certificados solo a los propietarios de servidores y dominios debidamente verificados., En casos raros, Las Ca son engañadas o, en el caso de Comodo o DigiNotar,violadas, lo que resulta en los certificados para un nombre de host que se emitirá a alguien que no sea el propietario del servidor o dominio.
para mitigar este riesgo, Android tiene la capacidad de agregar ciertos certificados o CA en su totalidad a una denylist. Si bien esta lista se integró históricamente en el sistema operativo, startingin Android 4.2 esta lista se puede actualizar de forma remota para hacer frente a futuros compromisos.,
fijación
Una aplicación puede protegerse aún más de los certificados emitidos fraudulentamente por atechnique conocidos como fijación. Esto básicamente está utilizando el ejemplo proporcionado en el caso de CA desconocido para restringir las CA de confianza de una aplicación a un pequeño conjunto conocido por ser utilizado por los servidores de la aplicación. Esto evita que el compromiso de una de las otras 100+ CA en el sistema resulte en una violación del canal seguro de aplicaciones.
certificados de cliente
Este artículo se ha centrado en el usuario de SSL para proteger las comunicaciones con los servidores., SSL también admite la noción de certificados de cliente que permiten al servidor validar la identidad de aclient. Mientras que más allá del alcance de este artículo, Las técnicas involucradas son similares a specifyinga custom TrustManager
.
Nogotofail: una herramienta de prueba de seguridad de tráfico de red
Nogotofail es una herramienta que le brinda una manera fácil de confirmar que sus aplicaciones están seguras contra vulnerabilidades y configuraciones erróneas conocidas de TLS/SSL. Es una herramienta automatizada, potente y escalable para probar problemas de seguridad de red en cualquier dispositivo cuyo tráfico de red se pueda hacer pasar por él.,
Nogotofail es útil para tres casos de Uso Principales:
- encontrar errores y vulnerabilidades.
- verificando correcciones y observando regresiones.
- entender qué aplicaciones y dispositivos están generando qué tráfico.
Nogotofail funciona para Android, iOS, Linux, Windows, Chrome OS, OSX, de hecho, cualquier dispositivo que utilice para conectarse a Internet. Hay un cliente fácil de usar para configurar los ajustes y obtener notificaciones en Android y Linux, así como el motor de ataque en sí que se puede implementar como un enrutador, servidor VPN o proxy.