Seguridad de acceso a la memoria

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 28 de junio de 2021; las comprobaciones requieren 6 ediciones .

La seguridad de acceso a la memoria  es un concepto en el desarrollo de software que tiene como objetivo evitar errores que generen vulnerabilidades relacionadas con el acceso a la RAM de una computadora , como desbordamientos de búfer y punteros colgantes .

Los lenguajes de programación con un bajo nivel de abstracción, como C y C++ , que admiten acceso directo a la memoria de la computadora ( aritmética de punteros arbitrarios , asignación y desasignación de memoria ) y conversión de tipos , pero no tienen verificación automática de límites de matriz seguros. en términos de acceso a la memoria [1] [2] . Sin embargo, C y C++ proporcionan herramientas (como punteros inteligentes ) para mejorar la seguridad del acceso a la memoria. Las técnicas de gestión de memoria tienen el mismo propósito [3]. Sin embargo, evitar errores de acceso a la memoria, especialmente en sistemas complejos, a menudo no es posible [4] .

Vulnerabilidades de acceso a la memoria

Una de las clases más comunes de vulnerabilidades de software son los problemas de seguridad de la memoria [5] [6] . Este tipo de vulnerabilidad se conoce desde hace más de 30 años [7] . La seguridad de la memoria significa evitar intentos de usar o modificar datos a menos que el programador lo haya permitido intencionalmente al crear el producto de software [8] .

Muchos programas críticos para el rendimiento se implementan en lenguajes de programación con un bajo nivel de abstracción ( C y C++ ), que son propensos a este tipo de vulnerabilidad. La falta de seguridad de estos lenguajes de programación permite a los atacantes obtener control total sobre el programa, cambiar el flujo de control y tener acceso no autorizado a información confidencial [9] . Por el momento, se han propuesto diversas soluciones a problemas relacionados con el acceso a la memoria. Los mecanismos de protección deben ser efectivos tanto en términos de seguridad como de desempeño [10] .

Los errores de memoria se publicaron por primera vez en 1972 [11] . Y luego fueron el problema de muchos productos de software, una herramienta que te permite usar exploits . Por ejemplo, el gusano Morris utilizó muchas vulnerabilidades, algunas de las cuales estaban relacionadas con errores de memoria [12] .

Tipos de errores de memoria

Hay varios tipos de errores de memoria (vulnerabilidades) que pueden ocurrir en algunos lenguajes de programación: [13] [14] [15]

Detección de errores

Los posibles errores de trabajar con la memoria se pueden detectar tanto durante la compilación del programa como durante la ejecución ( depuración ).

Además de las advertencias del compilador, se utilizan analizadores de código estático para detectar errores antes de compilar el programa . Le permiten cubrir una parte importante de las situaciones peligrosas examinando el código fuente con más detalle que un análisis superficial del compilador. Los analizadores estáticos pueden detectar: ​​[44] [45] [46] [47]

Durante la depuración del programa, se pueden usar administradores de memoria especiales. En este caso, se crean áreas de memoria "muertas" alrededor de los objetos asignados en el montón, y cuando el depurador entra en ellas, puede detectar errores [48] . Una alternativa son las máquinas virtuales especializadas que comprueban el acceso a la memoria ( Valgrind ). La detección de errores es asistida por sistemas de instrumentación de código , incluidos los proporcionados por el compilador (Sanitizer [49] ).

Métodos de seguridad

La mayoría de los lenguajes de alto nivel resuelven estos problemas eliminando la aritmética de punteros del lenguaje, limitando la capacidad de conversión e introduciendo la recolección de basura como el único esquema de administración de memoria [50] . A diferencia de los lenguajes de bajo nivel , donde la velocidad es importante, los lenguajes de alto nivel en su mayoría realizan verificaciones adicionales [51] , como la verificación de límites al acceder a matrices y objetos [52] .

Para evitar fugas de memoria y recursos y garantizar la seguridad de las excepciones, el C++ moderno utiliza punteros inteligentes . Por lo general, son una clase que imita la interfaz de un puntero ordinario y agrega funcionalidad adicional [53] , como verificar los límites de matrices y objetos, administrar automáticamente la asignación y desasignación de memoria para el objeto que se está utilizando. Ayudan a implementar el idioma de programación de adquisición de recursos es inicialización (RAII), en el que la adquisición de un objeto está inextricablemente vinculada con su inicialización, y la liberación está inextricablemente vinculada con su destrucción [54] .

Al usar funciones de biblioteca, debe prestar atención a sus valores de retorno para detectar posibles violaciones en su funcionamiento [55] . Las funciones para trabajar con memoria dinámica en C señalan un error (falta de memoria libre del tamaño solicitado) al devolver un puntero nulo en lugar de un puntero a un bloque de memoria [56] ; C++ usa excepciones [57] . El manejo adecuado de estas situaciones le permite evitar la finalización incorrecta (anormal) del programa [58] .

Las verificaciones de límites al usar punteros mejoran la seguridad. Estos controles se agregan en tiempo de compilación y pueden ralentizar los programas; Se han desarrollado extensiones de hardware especiales (por ejemplo, Intel MPX [59] ) para acelerarlos .

En los niveles más bajos de abstracción , existen sistemas especiales que brindan seguridad a la memoria. A nivel del sistema operativo, este es un administrador de memoria virtual que separa las áreas de memoria disponibles para los procesos individuales ( soporte multitarea ) y las funciones de sincronización para soportar subprocesos múltiples [60] . La capa de hardware también suele incluir algunos mecanismos como anillos de protección [61] .

Notas

  1. Erik Poll. Apuntes de clase sobre seguridad basada en lenguaje . - Universidad Radboud Nijmegen, 2016. - 21 de enero. / "Las características del lenguaje que rompen la seguridad de la memoria incluyen..."
  2. Laszlo Szekeres, Mathias Payer, Canción del amanecer. SoK: Guerra eterna en la memoria . — Simposio IEEE sobre seguridad y privacidad de 2013, 2013. / “Los errores de corrupción de memoria en software escrito en lenguajes de bajo nivel como C o C++ son uno de los problemas más antiguos en seguridad informática”.
  3. Fundación de la norma ISO C++. Preguntas frecuentes de C++:  administración de memoria . isocpp.org . Consultado el 10 de febrero de 2022. Archivado desde el original el 10 de septiembre de 2018.
  4. Fundación de la norma ISO C++. Preguntas frecuentes de C++:  administración de memoria . isocpp.org . Consultado el 10 de febrero de 2022. Archivado desde el original el 10 de septiembre de 2018. / "Claramente, si su código tiene operaciones nuevas, operaciones de eliminación y aritmética de punteros por todas partes, se equivocará en alguna parte y obtendrá fugas, punteros extraviados, etc." Esto es cierto independientemente de cuán concienzudo sea con sus asignaciones: eventualmente, la complejidad del código superará el tiempo y el esfuerzo que puede permitirse".
  5. Victor van der Veen, Nitish dutt-Sharma, Lorenzo Cavallaro, Herbert Bos. Errores de memoria: el pasado, el presente y el futuro . — RAID'12; Ámsterdam, Países Bajos, 2012. - 12-14 de septiembre. / "... y aún figura entre los 3 errores de software más peligrosos".
  6. Canción del amanecer. Seguridad de la memoria - Ataques y Defensas . - Berkeley CS161 Seguridad Informática, 2015. - Primavera. / "De hecho, después de los errores de configuración, los errores de implementación son probablemente la clase más grande de errores de seguridad explotados en la práctica".
  7. Laszlo Szekeres, Mathias Payer, Canción del amanecer. SoK: Guerra eterna en la memoria . — Simposio IEEE 2013 sobre Seguridad y Privacidad, 2013. / «Este problema existe desde hace más de 30 años…»
  8. Canción del amanecer. Seguridad de la memoria - Ataques y Defensas . - Berkeley CS161 Seguridad Informática, 2015. - Primavera. / "... impidiendo que los atacantes lean o escriban en ubicaciones de memoria distintas a las previstas por el programador".
  9. Laszlo Szekeres, Mathias Payer, Canción del amanecer. SoK: Guerra eterna en la memoria . — Simposio IEEE sobre seguridad y privacidad de 2013, 2013. / Las aplicaciones escritas en lenguajes de bajo nivel como C o C++ son propensas a este tipo de errores. La falta de seguridad de la memoria... permite a los atacantes aprovechar los errores de memoria alterando maliciosamente el comportamiento del programa o incluso tomando el control total del flujo de control".
  10. Laszlo Szekeres, Mathias Payer, Canción del amanecer. SoK: Guerra eterna en la memoria . — Simposio IEEE 2013 sobre seguridad y privacidad, 2013 .
  11. Victor van der Veen, Nitish dutt-Sharma, Lorenzo Cavallaro, Herbert Bos. Errores de memoria: el pasado, el presente y el futuro . — RAID'12; Ámsterdam, Países Bajos, 2012. - 12-14 de septiembre. / "Los errores de memoria se discutieron públicamente por primera vez en 1972 por el Panel de estudio de planificación de tecnología de seguridad informática".
  12. Victor van der Veen, Nitish dutt-Sharma, Lorenzo Cavallaro, Herbert Bos. Errores de memoria: el pasado, el presente y el futuro . — RAID'12; Ámsterdam, Países Bajos, 2012. - 12-14 de septiembre. / "El gusano de Internet explotó una serie de vulnerabilidades, incluidas las relacionadas con errores de memoria".
  13. Laszlo Szekeres, Mathias Payer, Canción del amanecer. SoK: Guerra eterna en la memoria . — Simposio IEEE 2013 sobre seguridad y privacidad, 2013.
  14. Canción del amanecer. Seguridad de la memoria - Ataques y Defensas . - Berkeley CS161 Seguridad Informática, 2015. - Primavera.
  15. Katrina Tsipenyuk, Brian Chess, Gary McGraw. Siete reinos perniciosos: una taxonomía de los errores de seguridad del software . - Taller del NIST sobre herramientas, técnicas y métricas de aseguramiento de la seguridad del software, Long Beach, CA, 2005. - Noviembre.
  16. Edsger W. Dijkstra. Por qué la numeración debe comenzar en cero (EWD 831) . - Plataanstraat 5, 5671 AL NUENEN, Países Bajos, 1982. - 11 de agosto. / "... el uso de las otras tres convenciones ha sido fuente constante de torpezas y errores..."
  17. Richard Jones y Paul Kelly. Comprobación de límites para C . - Colegio Imperial, 1995. - Julio. / "Una respuesta a este análisis es descartar C, ya que esta falta de verificabilidad eficiente es responsable de muchas fallas de software".
  18. John Ericson. Hackear. El arte de la hazaña . - San Petersburgo. : Símbolo-Plus, 2010. - S.  139 . — ISBN 978-5-93286-158-5 .
  19. John Ericson. Hackear. El arte de la hazaña . - San Petersburgo. : Símbolo-Plus, 2010. - S.  142 . — ISBN 978-5-93286-158-5 .
  20. David A. Wheeler. CÓMO de Programación Segura . — Publicado v3.72. — 2015. / “Los desbordamientos de búfer son una falla de seguridad extremadamente común y peligrosa…”
  21. Enumeración de debilidades comunes. CWE-126: Sobrelectura de búfer (8 de diciembre de 2015). Consultado el 24 de noviembre de 2016. Archivado desde el original el 27 de septiembre de 2016. / "Esto suele ocurrir cuando el puntero o su índice se incrementa a una posición más allá de los límites del búfer..."
  22. Steve Christey. 2011 CWE/SANS Los 25 errores de software más peligrosos . MITRE (13 de septiembre de 2011). Consultado el 24 de noviembre de 2016. Archivado desde el original el 12 de abril de 2018.
  23. Guy Keren. Gestión de memoria en tiempo de ejecución de Unix y C/C++ para programadores (enlace no disponible) (2001-2002). Consultado el 24 de noviembre de 2016. Archivado desde el original el 27 de septiembre de 2016.   / "El entorno de tiempo de ejecución define no solo cómo se asigna y libera la memoria..."
  24. Robert C. Seacord. Codificación segura en C y C++ . — Addison-Wesley, 2013. — Pág  . 162 . - ISBN 978-0-321-82213-0 .
  25. Jonathan Afek, Adi Sharabani. Puntero colgante. Rompiendo el puntero por diversión y beneficio . — Corporación Watchfire, 2007.
  26. Periódico informático. Un enlace a ninguna parte, o un puntero roto . Consultado el 24 de noviembre de 2016. Archivado desde el original el 22 de junio de 2018. / "... vulnerabilidades que pueden ser causadas por el mal uso de punteros y referencias".
  27. Enumeración de debilidades comunes. CWE-416: Use After Free (08 de diciembre de 2015). Consultado el 24 de noviembre de 2016. Archivado desde el original el 18 de julio de 2019. / "Hacer referencia a la memoria después de que se haya liberado puede hacer que un programa se bloquee, use valores inesperados o ejecute código".
  28. Juan Caballero, Gustavo Grieco, Mark Marrón, Antonio Nappa. Undangle: Detección temprana de punteros colgantes en vulnerabilidades Use-After-Free y Double-Free . — Instituto IMDEA Software; Madrid, España. / "Las vulnerabilidades use-after-free están creciendo rápidamente en popularidad, especialmente para explotar los navegadores web".
  29. comp.lang.c. Pregunta 5.1 . Consultado el 24 de noviembre de 2016. Archivado desde el original el 27 de septiembre de 2016. / "La definición del lenguaje establece que para cada tipo de puntero, existe un valor especial..."
  30. Oráculo. Plataforma Java, especificación de API Standard Edition 7 . Consultado el 24 de noviembre de 2016. Archivado desde el original el 23 de abril de 2018. / "Lanzado cuando una aplicación intenta usar nulo en un caso donde se requiere un objeto".
  31. Enumeración de debilidades comunes. CWE-415: Doble Gratis (08 de diciembre de 2015). Consultado el 24 de noviembre de 2016. Archivado desde el original el 27 de septiembre de 2016. / "Cuando un programa llama a free() dos veces con el mismo argumento..."
  32. YanHuang. Desbordamientos de montón y ataques sin dobles . Consultado el 24 de noviembre de 2016. Archivado desde el original el 17 de abril de 2018. / "Si free(p) ya ha sido llamado antes, se produce un comportamiento indefinido".
  33. Andréi Alexandrescu. Diseño C++ moderno: programación genérica y patrones de diseño aplicados . - Addison Wesley, 2001.  (enlace no disponible) / "... por lo general se implementa como un envoltorio delgado alrededor del asignador de montón C..."
  34. Guy Keren. Gestión de memoria en tiempo de ejecución de Unix y C/C++ para programadores (enlace no disponible) (2001-2002). Consultado el 25 de noviembre de 2016. Archivado desde el original el 27 de septiembre de 2016.   / "Por ejemplo, el operador new del compilador GNU C++ en realidad invoca la función malloc() en tiempo de ejecución de C".
  35. Gestión de la memoria . Consultado el 25 de noviembre de 2016. Archivado desde el original el 10 de septiembre de 2018. / "Los operadores de C++ new y delete garantizan una construcción y destrucción adecuadas... Las funciones de estilo C... no garantizan eso".
  36. OWASP. fuga de memoria . Consultado el 25 de noviembre de 2016. Archivado desde el original el 23 de noviembre de 2016.
  37. Cuestiones relacionadas con los punteros . Fecha de acceso: 25 de noviembre de 2016. Archivado desde el original el 26 de febrero de 2013. / "¡Nada es más perturbador que los punteros 'salvajes'!"
  38. Escama de Halvar. Ataques a variables locales no inicializadas (2006). Consultado el 25 de noviembre de 2016. Archivado desde el original el 3 de junio de 2016. / "Estamos viendo la siguiente situación entonces..."
  39. Enumeración de debilidades comunes. CWE-457: Uso de variable no inicializada (8 de diciembre de 2015). Consultado el 25 de noviembre de 2016. Archivado desde el original el 2 de octubre de 2016. / "Un atacante a veces puede controlar o leer estos contenidos".
  40. Uso y portabilidad de GNU Fortran . James Craig, Burley (1 de junio de 1991). Fecha de acceso: 25 de noviembre de 2016. Archivado desde el original el 5 de octubre de 2012.
  41. Danny Kalev. Comprender el desbordamiento de pila (5 de septiembre de 2000). Fecha de acceso: 25 de noviembre de 2016. Archivado desde el original el 5 de octubre de 2012. / "Las dos causas más comunes de un desbordamiento de pila..."
  42. John Boyland. Documento de posición: manejo de errores de "memoria insuficiente" . — Universidad de Wisconsin-Milwaukee, Estados Unidos. Archivado desde el original el 22 de marzo de 2016. / "Un error de "memoria insuficiente" puede ser catastrófico para un programa, especialmente uno escrito en un lenguaje como Java que utiliza la asignación de memoria con frecuencia".
  43. Mulyadi Santosa. Cuando Linux se queda sin memoria (30/11/2006). Consultado el 15 de noviembre de 2016. Archivado desde el original el 14 de abril de 2018. / "... ya no puede asignar más memoria y el kernel elimina una tarea (generalmente la que se está ejecutando actualmente)".
  44. Anders Moller y Michael I. Schwartzbach. Análisis de programas estáticos . - Departamento de Ciencias de la Computación, Universidad de Aarhus, 2015. - Mayo.
  45. Cppcheck: una herramienta para el análisis de código C/C++ estático . Consultado el 25 de noviembre de 2016. Archivado desde el original el 18 de enero de 2016. / "Detecta varios tipos de errores en tu código..."
  46. Diseños semánticos. Análisis de seguridad de la memoria con CheckPointer . Consultado el 25 de noviembre de 2016. Archivado desde el original el 18 de abril de 2018. / "Los programas con punteros pueden cometer una variedad de errores al acceder a la memoria..."
  47. PVS-Studio. Análisis de código estático (25/03/2015). Consultado el 25 de noviembre de 2016. Archivado desde el original el 25 de enero de 2018.
  48. Emery D. Berger, Benjamin G. Zorn. DieHard: Seguridad de la memoria probabilística para lenguajes inseguros . — PLDI'06; Ottawa, Ontario, Canadá, 2006. 11-14 de junio.
  49. Konstantin Serebryany, Dmitry Vyukov. Encontrar carreras y errores de memoria con la instrumentación del compilador . Caldero de herramientas GNU (10 de julio de 2012). Consultado el 25 de noviembre de 2016. Archivado desde el original el 12 de marzo de 2016.
  50. Erik Poll. Seguridad basada en lenguaje: lenguajes de programación 'seguros' (enlace descendente) . Radboud Universiteit Nijmegen . Consultado el 25 de noviembre de 2016. Archivado desde el original el 5 de noviembre de 2016.   / "La gestión manual de la memoria se puede evitar..."
  51. Dinakar Dhurjati y Vikram Adve. Comprobación de límites de matriz compatibles con versiones anteriores para C con sobrecarga muy baja . — Departamento de Ciencias de la Computación Universidad de Illinois en Urbana-Champaign. / "... un problema sin resolver a pesar de un largo historial de trabajo en la detección de violaciones de los límites de la matriz o desbordamientos del búfer, porque las mejores soluciones existentes hasta la fecha son demasiado costosas para su uso en el código de producción implementado..."
  52. Bruce Eckel. Pensando en Java. Cuarta Edición . / "Tanto las matrices como los contenedores garantizan que no se puede abusar de ellos. Ya sea que esté utilizando una matriz o un contenedor, obtendrá una RuntimeException si excede los límites, lo que indica un error del programador".
  53. David Kieras. Usando los punteros inteligentes de C++11 . - Departamento EECS, Universidad de Michigan, 2016. - Junio. / "Los punteros inteligentes son objetos de clase que se comportan como punteros incorporados pero también administran objetos que usted crea..."
  54. Red de desarrolladores de Microsoft. Punteros inteligentes (C++ moderno) . Consultado el 25 de noviembre de 2016. Archivado desde el original el 5 de diciembre de 2017. / "Son extremadamente importantes para el lenguaje de programación RAII o la adquisición de recursos es inicialización..."
  55. Enumeración de debilidades comunes. CWE-252: Valor de retorno no verificado (8 de diciembre de 2015). Consultado el 25 de noviembre de 2016. Archivado desde el original el 18 de julio de 2019. / "El software no verifica el valor de retorno de un método o función, lo que puede evitar que detecte estados y condiciones inesperados".
  56. Red de desarrolladores de Microsoft. malloc _ Consultado el 25 de noviembre de 2016. Archivado desde el original el 5 de octubre de 2016. / "malloc devuelve un puntero sin tipo al área de memoria asignada, o NULL si no hay suficiente memoria disponible".
  57. operador nuevo, operador nuevo[ ] . Consultado el 25 de noviembre de 2016. Archivado desde el original el 29 de marzo de 2018. / "arroja std::bad_alloc u otra excepción derivada de std::bad_alloc (desde C++11) al no poder asignar memoria"
  58. Paul y Harvey Deitel. C: cómo programar .
  59. Zona de desarrolladores de Intel. Introducción a Intel® Memory Protection Extensions (16 de julio de 2013). Consultado el 25 de noviembre de 2016. Archivado desde el original el 5 de mayo de 2019.
  60. Sarah Diesburg. Protección de memoria: Kernel y espacios de direcciones de usuario . Consultado el 25 de noviembre de 2016. Archivado desde el original el 9 de agosto de 2017.
  61. Michael D. Schroeder y Jerome H. Saltzer. Una arquitectura de hardware para implementar anillos de protección . - Tercer Simposio ACM sobre Principios de Sistemas Operativos, Palo Alto, California, 1971. - 18-20 de octubre.

Literatura

Enlaces

Publicaciones Generales

Publicaciones temáticas