search

Integrando Rust en la baseband de Pixel

person Por Edward Fernandez
source Fuente: Google Online Security Blog
calendar_today
schedule 7 min de lectura

Google está continuamente mejorando la seguridad de los dispositivos Pixel. Nos hemos centrado en endurecer el módem celular contra las explotaciones. Reconociendo los riesgos asociados con el firmware complejo del módem, el Pixel 9 incluía mitigaciones contra una gama de vulnerabilidades de seguridad de memoria. Para el Pixel 10, Google está mejorando sus medidas de seguridad proactivas. Siguiendo nuestra discusión anterior sobre la implementación de Rust en bases de código de firmware existentes, esta publicación comparte una aplicación concreta: integrar un analizador DNS seguro en memoria Rust en el firmware del módem. El nuevo analizador DNS basado en Rust reduce significativamente nuestro riesgo de seguridad al mitigar una clase completa de vulnerabilidades en una zona de alto riesgo, al mismo tiempo que establece las bases para una adopción más amplia de código seguro en la memoria en otras áreas. Aquí compartimos nuestra experiencia trabajando en ello, y esperamos que inspire el uso de más lenguajes seguros en memoria en entornos de bajo nivel. La seguridad de memoria del módem es esencial. En los últimos años, hemos visto un creciente interés de los atacantes y los investigadores en seguridad en el módem celular. Por ejemplo, el Proyecto Zero de Google logró la ejecución remota de código en los módems Pixel a través de Internet. Los módems tienen decenas de megabytes de código ejecutable. Dado la complejidad y la superficie de ataque del módem, otras vulnerabilidades críticas de seguridad de memoria podrían permanecer en el firmware no seguro. ¿Por qué el DNS? El protocolo DNS es más comúnmente conocido en el contexto de los navegadores para encontrar sitios web. Con la evolución de la tecnología celular, las comunicaciones celulares modernas se han migrado a redes de datos digitales; por lo tanto, incluso operaciones básicas como el reenvío de llamadas dependen de los servicios DNS. El DNS es un protocolo complejo y requiere el análisis de datos no confiables, lo que puede conducir a vulnerabilidades, particularmente cuando se implementa en un lenguaje inseguro en memoria (por ejemplo, CVE-2024-27227). Implementar el analizador DNS en Rust ofrece valor al reducir las superficies de ataque asociadas con la inseguridad en la memoria. Selección de una biblioteca DNS. Ya existe cierto nivel de soporte para Rust en la comunidad de código abierto. Evaluamos varias librerías de código abierto que implementan DNS. Basándonos en los criterios compartidos en publicaciones anteriores, identificamos hickory-proto como la mejor candidata. Tiene un excelente mantenimiento, más del 75% de la cobertura de pruebas y una amplia adopción en la comunidad Rust. Su pervasividad indica su potencial como la opción DNS predeterminada y el soporte a largo plazo. Aunque hickory-proto inicialmente carecía de soporte no_std, que es necesario para los entornos de bare-metal (como se discutió en nuestra publicación anterior), logramos agregar soporte para ello y sus dependencias. Agregando soporte no_std. El trabajo para habilitar no_std para hickory-proto es principalmente mecánico. Compartimos el proceso en una publicación anterior. Realizamos modificaciones a hickory_proto y sus dependencias para habilitar el soporte no_std. El trabajo de no_std también resulta en un analizador de URL no_std, lo que es beneficioso para otros proyectos. Se incluyeron enlaces a las solicitudes de extracción de GitHub. Estudio del tamaño del código. El tamaño del código es uno de los factores que evaluamos al elegir la biblioteca DNS que usar. Rust implementó un shim que llama a Hickory-proto al recibir una respuesta DNS de 4KB core, alloc, compiler_builtins (reutilizable, costo único) 17KB Hickory-proto library y dependencies 350KB Sum 371KB. Construimos prototipos y medimos el tamaño con configuraciones optimizadas para el tamaño. Como se esperaba, hickory-proto no está diseñado para uso incrustado y no está optimizado para el tamaño. Dado que el módem Pixel no tiene restricciones de memoria, priorizamos el soporte de la comunidad y la calidad del código, dejando la optimización del tamaño del código como trabajo futuro. Sin embargo, el aumento del tamaño del código puede ser un obstáculo para otros sistemas integrados. Esto podría abordarse en el futuro agregando características adicionales para compilar solo la funcionalidad necesaria. Implementar esta modularidad sería un trabajo valioso en el futuro. Conexión de Rust a firmware del módem. Antes de construir la biblioteca DNS de Rust, definimos varias pruebas unitarias de Rust para cubrir aritmética básica, asignaciones dinámicas y FFI para verificar la integración del código de firmware del módem existente. Compilación del código de Rust a estático. Si bien cargo es la opción predeterminada para la compilación en el ecosistema de Rust, presenta desafíos al integrarlo en sistemas de construcción existentes. Evaluamos dos opciones: Usar cargo para construir un estático antes de que el módem construya. Luego agregar el estático a la etapa de enlazado. Trabajar directamente con rustc e integrar los pasos de compilación de Rust en el sistema de construcción del módem existente. La opción #1 no escala si vamos a agregar más componentes de Rust en el futuro, ya que enlazar múltiples estáticos puede causar errores de símbolos duplicados. Optamos por la opción #2 ya que se escala más fácilmente e integra más estrechamente con nuestro sistema de construcción existente. Nuestro código base C/C++ existente usa Pigweed para impulsar el principal sistema de construcción. Pigweed soporta objetivos de Rust (por ejemplo) con llamadas directas a rustc a través de las herramientas de rust definidas en GN. Compilamos todas las librerías de Rust, incluyendo hickory-proto, sus dependencias y core, alloc, compiler_builtins a rlib. Luego, creamos un objetivo estático con un solo archivo lib.rs que hace referencia a todas las librerías rlib usando palabras clave extern crate. Construimos core, alloc, y compiler_builtins usando el Kit de herramientas de Rust para Android, que proporciona el código fuente de core, alloc, y compiler_builtins. Esto se puede incluir en el gráfico de construcción agregando un objetivo GN con crate_root que apunta al archivo lib.rs raíz de cada crate. El firmware del módem Pixel ya tiene un sistema de asignación de memoria global probado y especializado para admitir algunas asignaciones de memoria dinámicas. El soporte para alloc se agregó implementando la GlobalAlloc con llamadas FFI a las APIs C de los allocators: use core::alloc::{GlobalAlloc, Layout}; extern C { fn mem_malloc(size: usize, alignment: usize) -> *mut u8; fn mem_free(ptr: *mut u8, alignment: usize); } struct MemAllocator; unsafe impl GlobalAlloc for MemAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { mem_malloc(layout.size(), layout.align()) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { mem_free(ptr, layout.align()); } } #[global_allocator] static ALLOCATOR: MemAllocator = MemAllocator; El firmware del módem Pixel ya implementa un backend para la fachada de fallos de Pigweed como el manejador de fallos global. Esto expone en Rust a través de FFI a través de la función panic_handler unifica el manejo de fallos para Rust y C/C++. #[no_std] use core::panic::PanicInfo; extern C { pub fn PwCrashBackend(sigature: *const i8, file_name: *const i8, line: u32); } #[panic_handler] fn panic(panic_info: &PanicInfo) -> ! { let mut filename = ; let mut line_number: u32 = 0; if let Some(location) = panic_info.location() { filename = location.file(); line_number = location.line(); } let mut cstr_buffer = [0u8; 128]; // Nunca escribe en el último byte para asegurarse de que cstr_buffer siempre esté terminado con cero // . Usamos split_last_mut para obtener un muto escritor. Para cada (place, ch) en writer.iter_mut().zip(filename.bytes()) { *place = ch; } unsafe { PwCrashBackend( Rust panic\0.as_ptr() as *const i8, cstr_buffer.as_ptr() as *const i8, line_number, ); } loop {} } En nuestro caso, la API de análisis de respuesta DNS es lo suficientemente simple para nosotros para escribirla a mano, mientras que las funciones de retorno de llamada a C para el manejo de la respuesta son complejas. Por lo tanto, utilizamos bindgen para generar código FFI para las llamadas. Construcción de librerías de terceros. Incluso con todas las características deshabilitadas, hickory-proto introduce más de 30 librerías dependientes. Las reglas de construcción escritas a mano son difíciles de garantizar la corrección y no escalan bien cuando se actualizan las dependencias a nuevas versiones. Fuchsia ha desarrollado cargo-gnaw para admitir la construcción de sus librerías de terceros de Rust. cargo-gnaw funciona invocando a cargo metadata para resolver dependencias, luego analizando y generando reglas de construcción GN. Esto garantiza la corrección y la facilidad de mantenimiento. Conclusión La serie Pixel 10 marca un momento crucial, al ser el primer dispositivo Pixel que integra un lenguaje seguro en memoria en su módem. Si bien reemplazar una superficie de ataque es en sí mismo valioso, este proyecto sienta las bases para la futura integración de analizadores y código seguros en memoria en el módem celular, asegurando que la postura de seguridad del módem mejorará continuamente. Gracias especiales a Armando Montanez, Bjorn Mellem, Boky Chen, Cheng-Yu Tsai, Dominik Maier, Erik Gilling, Ever Rosales, Hungyen Weng, Ivan Lozano, James Farrell, Jeffrey Vander Stoep, Jiacheng Lu, Jingjing Bu, Min Xu, Murphy Stein, Ray Weng, Shawn Yang, Sherk Chung, Stephan Chen, Stephen Hines.

Artículos relacionados

cybersecurity

Nueva campaña norcoreana utiliza entrevistas de programación falsas para robar credenciales de desarrolladores

Hackers afiliados a Corea del Norte escondieron malware en imágenes de banderas SVG para realizar pruebas de programación durante las entrevistas para puestos de trabajo. Ninguna empresa de software antivirus lo detectó.

cybersecurity

Abbott investiga dos incidentes cibernéticos a raíz de las denuncias de extorsión

Abbott Laboratories está investigando dos incidentes de ciberseguridad separados después de confirmar el acceso no autorizado a sistemas internos Exact Sciences de su negocio de diagnóstico del cáncer, así como una reclamación separada de que los atacantes accedieron al portal de LabCentral y robaron datos de la empresa.

cybersecurity

La vulnerabilidad HollowByte de ataque DDoS infla la memoria del servidor OpenSSL con un payload de 11 bytes

Una vulnerabilidad denominada HollowByte permite a atacantes no autenticados provocar una condición de denegación de servicio (DoS) en servidores OpenSSL con una carga maliciosa de solo 11 bytes.