Cómo asegurar C



El lenguaje C es muy poderoso y se usa mucho donde, especialmente en el kernel de Linux, pero también es muy peligroso. Un desarrollador de kernel de Linux describió cómo lidiar con las vulnerabilidades de seguridad de C.

Puede hacer casi cualquier cosa en C, pero esto no significa que deba hacerse. El código C es muy rápido, pero se lleva sin cinturones de seguridad. Incluso si usted es un experto, como la mayoría de los desarrolladores de kernel de Linux , aún son posibles errores asesinos.

Además de las trampas como los alias de puntero , el lenguaje C tiene errores fundamentales no corregidos que esperan a sus víctimas. Estas son las vulnerabilidades que Case Cook , ingeniero de seguridad del kernel de Google Linux, abordó en la Linux Security Conference en Vancouver.

“C es una especie de ensamblador. Es casi código de máquina ", dijo Cook, refiriéndose a una audiencia de varios cientos de colegas que entienden y aprecian la velocidad de las aplicaciones en C. Pero la mala noticia es que" C viene con un equipaje peligroso, un comportamiento vago y otras debilidades que conducen a agujeros de seguridad e infraestructura vulnerable ".

Si usa C en sus proyectos, debe prestar atención a los problemas de seguridad.

Protección del kernel de Linux


Con el tiempo, Cook y sus colegas descubrieron numerosos problemas con el nativo C. Para abordarlos, se lanzó el Kernel Self Protection Project . Lenta y constantemente trabaja para proteger el kernel de Linux de los ataques, eliminando el código problemático de allí.

Esto es complicado, dice Cook, porque "el núcleo necesita hacer cosas muy específicas para una arquitectura particular para la administración de la memoria, el manejo de interrupciones, la eliminación, etc." Una gran cantidad de código se refiere a tareas específicas que deben verificarse cuidadosamente. Por ejemplo, "C no tiene una API para configurar tablas de páginas o cambiar al modo de 64 bits", dijo.

Con tal carga y con bibliotecas estándar débiles en C, hay un comportamiento demasiado vago. Cook citó, y estuvo de acuerdo, con el artículo del blog de Raf Levien, "Con un comportamiento indefinido, todo es posible" .

Cook dio ejemplos específicos: "¿Cuál es el contenido de las variables" no inicializadas "? ¡Esto es todo lo que había en mi memoria antes! No hay tipos en punteros vacíos, pero ¿pueden llamarse las funciones tipadas a través de ellos? Por supuesto! El montaje es el mismo: ¡puedes contactar con cualquier dirección! ¿Por qué memcpy() tiene el argumento 'longitud máxima de destino'? No importa, solo haz lo que dices; ¡todas las áreas de memoria son iguales!

Ignorando las advertencias ... pero no siempre


Algunas de estas características son relativamente fáciles de manejar. Cook comentó: “A Linus [Torvalds] le gusta la idea de siempre inicializar variables locales. Así que solo hazlo ".

Pero con una reserva. Si inicializa una variable local en el conmutador, recibirá una advertencia: "La instrucción nunca se ejecutará [-Wswitch-unreachable] " debido a la forma en que el compilador procesa el código. Esta advertencia puede ser ignorada.

Pero no todas las advertencias pueden ser ignoradas. "Las matrices de longitud variable siempre son malas", dijo Cook. Otros problemas incluyen el agotamiento de la pila, el desbordamiento de línea y las infracciones de protección de página. Además, Cook llamó la atención sobre la lentitud de VLA . La eliminación de todos los VLA del núcleo aumentó el rendimiento en un 13%. Mejorar tanto la velocidad como la seguridad es un doble beneficio.

Aunque los VLA casi se eliminaron del núcleo, aún permanecían en algún código. Afortunadamente, los VLA son fáciles de encontrar utilizando el -Wvla compilador -Wvla .

Otro problema está oculto en la semántica de C. Si falta un descanso en el interruptor, ¿qué quiso decir el programador? Saltarse el descanso puede conducir a la ejecución del código desde varias condiciones; Este es un problema bien conocido.

Si está buscando declaraciones de interrupción / cambio en el código existente, puede usar -Wimplicit-fallthrough para agregar una nueva declaración de cambio. Esto es en realidad un comentario, pero los compiladores modernos lo analizan. También puede marcar explícitamente la ausencia de ruptura con un comentario "fallido" .

Cook también encontró un impacto en el rendimiento al verificar los límites para la asignación de memoria de losa . Por ejemplo, la comprobación de strcpy()-family reduce el rendimiento en un 2%. Las alternativas como strncpy() sus propios problemas. Resulta que Strncpy no siempre termina con un carácter nulo. Cook se dirigió tristemente a la audiencia: "¿Dónde puedo obtener las mejores API?"

Durante una sesión de preguntas y respuestas, un desarrollador de Linux preguntó: "¿Puedo deshacerme de las API viejas y malas?" Cook respondió que Linux apoyó el concepto de API heredadas por algún tiempo. Sin embargo, Torvalds rechazó esta idea, argumentando que si alguna API está desactualizada, debería descartarse por completo. Sin embargo, dejar caer la API para siempre es "políticamente peligroso", agregó Cook. Entonces, mientras estamos atrapados.

¿Solución a largo plazo al problema? Más desarrolladores entienden los problemas de seguridad


Cook prevé un largo y difícil viaje. La idea de crear un dialecto de Linux C alguna vez pareció atractiva, pero no lo será. El verdadero problema con el código peligroso es que "la gente no quiere hacer el trabajo de limpiar el código, no solo el código malo, sino el propio C", dijo. Al igual que con todos los proyectos de código abierto, "necesitamos desarrolladores, revisores, evaluadores y especialistas en backport más dedicados".

Dangerous C: lecciones


  • C es un lenguaje maduro y poderoso, pero crea dificultades técnicas y problemas de seguridad.
  • Los desarrolladores de Linux prestan especial atención a asegurar C (sin perder su potencia), porque la mayor parte del sistema operativo está escrito en él.
  • El ingeniero de seguridad del kernel de Linux Linux identificó vulnerabilidades específicas del lenguaje y explicó cómo evitarlas.

Source: https://habr.com/ru/post/es422623/


All Articles