Gravísimo error en sistemas operativos de Apple invalida el TLS/SSL. Goto failElevenPaths 24 febrero, 2014 Apple ha cometido un gravísimo (que casi roza el ridículo) error en su implementación de SecureTransport, una capa del sistema de gestión de TLS/SSL como ya han contado nuestros compañeros en Seguridad Apple. En resumen, introduciendo por error una línea de código, ha invalidado por completo el SSL en iOS y Mac OS X durante unos dos años, la criptografía más fundamental y pilar de la confianza web. Tan simple y absurda, que podría parecer intencionada. Veamos qué ha pasado y sus consecuencias. Apple lanzó una actualización muy urgente para iOS (no aún para Mac OS X que continúa con el problema). Como siempre, sin demasiados detalles y con vagas referencias a SSL. Pero poco después se descubrieron los detalles del problema. Código abierto en http://opensource.apple.com/source/Security/Security-55471/libsecurity_ssl/lib/sslKeyExchange.c Se observa una línea repetida «goto fail». La indentación es incorrecta y es lo que puede llevar a confusión, pero solo el primer «goto fail» está ligado al if. El segundo «goto fail» se ejecuta siempre, ocurra lo que ocurra con los if anteriores. Lo que quiere decir, que hay una parte del código a la que nunca se llega, y en la que se realiza una verificación importante relativa al intercambio de claves en el protocolo SSL. En otras palabras, si la operación SLHashSHA1.update es válida y «err» toma un valor válido, la verificación de la clave nunca dará error, aunque el resto de valores no se hayan comprobado. Para entender el fallo, nos ponemos un poco en situación con el protocolo SSL El protocolo SSL En TLS/SSL se puede utilizar Diffie/Hellman (DH) como protocolo de intercambio seguro de claves en un canal inseguro. Así, se negocia una clave DH efímera (se descarta después de cada uso) que permite el cifrado simétrico de la comunicación entre navegador y servidor. Pero TLS/SSL no solo permite cifrado sino que también autenticación. Para eso se utiliza el protocolo RSA y por supuesto los certificados. Estos se encargan de firmar la comunicación, es decir, garantizar que vienen del servidor correcto. El fallo se produce en el momento de enviar el mensaje ServerKeyExchange. En este momento es cuando el servidor le ofrece al navegador o cliente esa clave efímera, y la firma con su clave privada que, avalada por su certificado, no dejan lugar a dudas de que proviene de quien dice provenir. Pero, debido al error, esto no tiene por qué ser así. Se le puede comunicar una clave efímera, pero no firmarla, o firmarla con un certificado incorrecto. El navegador o cliente nunca se quejaría. En otras palabras, podrías conectarte a una página por https que no fuera la que dice ser, pero ningún aviso en el navegador te diría lo contrario. Limpiamente un atacante podría obtener toda la información de la comunicación. Eso sí, obviamente la red en la que se navega tendría que estar ya en cierta manera manipulada por el atacante, puesto que la víctima tendría que ser redirigida a nivel de dominio. Quizás, es una de las razones por las que Apple ha priorizado la solución para iOS. También por lo que se ha lanzado la teoría de la conspiración que siempre surge cuando se habla de la capacidad de descifrar las comunicaciones cifradas. Los gobiernos podrían tener la capacidad de desviar a los usuarios a servidores diferentes, puesto que podrían controlar los DNS de red. De hecho, algunos lo hacen. ¿Hay algo que mitigue el problema? ¿Y el certificate pinning? Ante este fallo, no serviría. El atacante podría enviar la cadena de certificados válidos, pero aun así una firma de la clave efímera perteneciente a otro, y el cliente SSL no se quejaría. ¿Y si no se usa DH para el intercambio de claves? No importaría, porque en SSL el servidor suele poder negociar qué suite de cifrado se quiere usar. Solo podrían librarse los navegadores o clientes que fuercen TLS 1.2 y no degraden a uno anterior aunque el servidor se lo solicite. Pocos navegadores lo hacen porque limitaría su capacidad de conexión con servidores que no lo soportan. ¿Lecciones aprendidas? El bug dará para muchas discusiones, análisis (y mofas) durante mucho tiempo. Pocas veces se observa un fallo tan importante y simple. Quizás remite al fallo criptográfico de Debian ocurrido en 2008 explicado en detalle en esta conferencia de Luciano Bello. En primer lugar, sorprende (bueno, quizás no tanto) que un fallo tan absurdo haya ocurrido en código abierto. ¿Cuánto tiempo estuvo ahí? El código desvela también malas prácticas en el estilo de programación (deberían haberse utilizado llaves para contener el if, evitar los gotos…). La indentación, que aunque se considera una buena práctica, ha jugado una mala pasada. Incluso desvela malas prácticas de compilación. Existen técnicas y comandos a la hora de compilar que permiten lanzar una alerta en tiempo de compilación cuando si se detecta código al que nunca se puede llegar. Desde luego, Apple ha cometido un error gravísimo y ha puesto no solo en peligro a sus usuarios, sino que ha dejado en entredicho la calidad de sus pruebas de software. ¿Soy vulnerable? Si se usa Mac OS X Mavericks, probablemente sí. Si usas iOS, se debe actualizar. El fallo fue introducido en la versión 6.0 de iOS, aparecido a mediados de 2012. El nivel de paranoia aumenta cuando se rumorea que Apple se adhirió a PRISM en octubre de ese año. En escritorio, se encuentra en Mavericks, pero no en anteriores. Ya existen páginas para comprobar si se es vulnerable. Aquí, y aquí. Fuente: https://twitter.com/0xabad1dea/status/437291365508976640 Por último, advertir de que el fallo no solo afecta al navegador. El problema está en librerías a bajo nivel a las que acuden todo tipo de clientes, y por tanto la vulnerabilidad va mucho más allá. Por ejemplo, pensemos en el proceso de actualización de software, el uso de correo, mensajería, etc. Cualquier cosa que utilice SSL para cifrar su tráfico y no necesariamente nativa del sistema operativo, sino que simplemente utilice sus librerías. Sergio de los Santos ssantos@11paths.com @ssantosv El negocio de las «FakeApps» y el malware en Google Play (I): IntroducciónEl negocio de las «FakeApps» y el malware en Google Play (II): Tipos de «fakes»
Carlos Rebato Criptografía, una herramienta para proteger los datos compartidos en la red Actualmente, la Ciberseguridad representa un aspecto primordial en las empresas. No obstante, cada día surgen nuevos modos de atentar contra ella. Muchos se han preguntado: ¿de qué manera las...
Roberto García Esteban ChatGPT y Cloud Computing: un matrimonio bien avenido ChatGPT (quizá no sepas que son las siglas de Chat Generative Pre-Trained Transformer) está en boca de todos por su impresionante habilidad para generar textos que parecen escritos por...
David Prieto Marqués La importancia del control de acceso: ¿está tu empresa protegida? Por David Prieto y Rodrigo Rojas En un mundo cada vez más digitalizado y complejo, la seguridad de la información es fundamental para las empresas. A medida que las empresas...
Telefónica Tech Boletín semanal de Ciberseguridad, 22 – 26 de mayo GitLab parchea una vulnerabilidad crítica GitLab ha abordado una vulnerabilidad crítica que afecta a GitLab Community Edition (CE) y Enterprise Edition (EE) en la versión 16.0.0. En concreto, dicho fallo...
David García ¿Salvará Rust el mundo? (II) Segunda entrega en la que descubrimos cómo Rust, el lenguaje de programación de código abierto centrado en la seguridad, mejora el panorama en cuanto a vulnerabilidades basadas en errores...
Sergio de los Santos Cuatro hitos en Ciberseguridad que marcaron el futuro del malware Un recorrido por los 15 años que ha dedicado Microsoft para consolidar una estrategia que ha repercutido en la Ciberseguridad a nivel global
Es que menudas prácticas más horrendas de programación! Primero… usando goto en programación estructurada (facepalm)… Aunque haya que "trabajar un poco más" hay que utilizar if y else. Es decir: En vez de: if (condición de error 1) goto error; if (condición de error 2) goto error; código sin error; return -1; error: código para error; return 0; Hay que hacer:if (condición de error 1 || condición de error 2 || condición de error 3) {código con error} else {código sin error} Segunda cagada (aunque de menor grado que usar goto). Lo dijo mi profesor de Ingeniería de software y cuanta razón tenía, es una práctica altamente recomendada en los lenguajes de la familia C utilizar siempre if (condición) {código} else {código} aunque solamente tengamos una única línea, es decir, no utilizar if (condición) línea; else línea; Es mucho más entendible para el programador (véase el caso) y además es reutilizable. Un saludo Responder
Pido disculpas porque hay una errata en mi anterior comentario. Dónde pone: goto error; código sin error; return -1; error: código para error; return 0; debería poner: goto error; código sin error; return 0; error: código para error; return -1; Un saludo. Responder