La seguretat de la memòria és l'estat d'estar protegit de diversos errors de programari i vulnerabilitats de seguretat quan es tracta d'accés a la memòria, com ara desbordaments de memòria intermèdia i punters penjants. Per exemple, es diu que Java és segur per a la memòria perquè la seva detecció d'errors en temps d'execució verifica els límits de la matriu i les referències de punters. En canvi, C i C++ permeten l'aritmètica arbitrària de punters amb punters implementats com a adreces de memòria directes sense cap disposició per a la verificació de límits, i per tant són potencialment insegurs per a la memòria.
Història Els errors de memòria es van considerar primer en el context de la gestió de recursos (informàtica) i els sistemes de temps compartit, en un esforç per evitar problemes com les bombes de forquilla. Els desenvolupaments van ser majoritàriament teòrics fins al cuc Morris, que va explotar un desbordament de tampó al dit. El camp de la seguretat informàtica es va desenvolupar ràpidament després, augmentant amb multitud de nous atacs, com ara l'atac de retorn a libc i tècniques de defensa com la pila no executable i l'aleatorització de la disposició de l'espai d'adreces. L'aleatorització impedeix la majoria dels atacs de desbordament de memòria intermèdia i requereix que l'atacant utilitzi la polvorització de pila o altres mètodes que depenen de l'aplicació per obtenir adreces, tot i que la seva adopció ha estat lenta. Tanmateix, els desplegaments de la tecnologia solen limitar-se a l'aleatorització de biblioteques i la ubicació de la pila.
Impacte El 2019, un enginyer de seguretat de Microsoft va informar que el 70% de totes les vulnerabilitats de seguretat eren causades per problemes de seguretat de la memòria. El 2020, un equip de Google va informar de la mateixa manera que el 70% de tots els "errors de seguretat greus" a Chromium van ser causats per problemes de seguretat de la memòria. Moltes altres vulnerabilitats i explotacions d'alt perfil del programari crític han derivat en última instància de la manca de seguretat de la memòria, inclosa Heartbleed i un error d'escalada de privilegis de llarga data a sudo. La omnipresencia i la gravetat de les vulnerabilitats i les explotacions derivades dels problemes de seguretat de la memòria han portat a diversos investigadors de seguretat a descriure la identificació dels problemes de seguretat de la memòria com "disparar peixos en un barril".
Aproximacions Alguns llenguatges de programació moderns d'alt nivell són segurs per a la memòria per defecte, encara que no del tot, ja que només comproven el seu propi codi i no el sistema amb el qual interactuen. La gestió automàtica de la memòria en forma de recollida d'escombraries és la tècnica més comuna per prevenir alguns dels problemes de seguretat de la memòria, ja que evita errors comuns de seguretat de la memòria com ara l'ús després de lliure per a totes les dades assignades dins del temps d'execució del llenguatge. Quan es combinen amb la comprovació automàtica de límits a tots els accessos a la matriu i sense suport per a l'aritmètica de punters sense processar, els llenguatges recollits de brossa ofereixen fortes garanties de seguretat de memòria (tot i que les garanties poden ser més febles per a operacions de baix nivell marcades explícitament com a no segures, com ara l'ús d'una interfície de funció estrangera). Tanmateix, la sobrecàrrega de rendiment de la recollida d'escombraries fa que aquests idiomes no siguin adequats per a determinades aplicacions crítiques per al rendiment.
Per als idiomes que utilitzen la gestió manual de la memòria, la seguretat de la memòria normalment no està garantida pel temps d'execució. En lloc d'això, el compilador ha de garantir les propietats de seguretat de la memòria mitjançant l'anàlisi de programes estàtic i la demostració automatitzada de teoremes o bé gestionades amb cura pel programador en temps d'execució. Per exemple, el llenguatge de programació Rust implementa un verificador de préstecs per garantir la seguretat de la memòria, mentre que C i C++ no ofereixen garanties de seguretat de memòria. La quantitat substancial de programari escrit en C i C++ ha motivat el desenvolupament d'eines externes d'anàlisi estàtica com Coverity, que ofereix anàlisi de memòria estàtica per a C.
Classificació dels errors de seguretat de la memòria Es poden produir molts tipus diferents d'errors de memòria:
Espacial Desbordament de la memòria intermèdia : les escriptures fora de límit poden corrompre el contingut dels objectes adjacents o les dades internes (com la informació de comptabilitat per a l'heap) o les adreces de retorn. Sobrelectura de la memòria intermèdia : les lectures fora de límit poden revelar dades sensibles o ajudar els atacants a evitar l'aleatorització del disseny de l'espai d'adreces. Temporal Utilitzar després de lliure : desreferenciar un punter penjant que emmagatzema l'adreça d'un objecte que s'ha suprimit. Doble lliure : les trucades repetides a lliure poden alliberar prematurament un objecte nou a la mateixa adreça. Si l'adreça exacta no s'ha reutilitzat, es poden produir altres corrupcions, especialment en els distribuïdors que utilitzen llistes gratuïtes. Variables no inicialitzades : s'utilitza una variable a la qual no se li ha assignat un valor. Pot contenir informació sensible o bits que no són vàlids per al tipus. Els punters salvatges sorgeixen quan s'utilitza un punter abans de la inicialització a algun estat conegut. Mostren el mateix comportament erràtic que els punters penjants, tot i que és menys probable que no es detectin. Lliure no vàlida : passar una adreça no vàlida a free pot corrompre l'heap. Gratuït no coincident : quan s'utilitzen diversos assignadors, s'intenta alliberar memòria amb una funció de desassignació d'un altre assignador
Errors que contribueixen Segons l'idioma i l'entorn, altres tipus d'errors poden contribuir a la inseguretat de la memòria:
Esgotament de la pila : es produeix quan un programa es queda sense espai de pila, normalment a causa d'una recursivitat massa profunda. Una pàgina de protecció normalment atura el programa, evitant la corrupció de la memòria, però les funcions amb marcs de pila grans poden passar per alt la pàgina i el codi del nucli pot no tenir el benefici de les pàgines de protecció. Esgotament del munt : el programa intenta assignar més memòria que la quantitat disponible. En alguns idiomes, aquesta condició s'ha de comprovar manualment després de cada assignació. Fuga de memòria : si no es retorna la memòria a l'assignador, es pot establir l'escenari per a l'esgotament de la pila (a dalt). No executar el destructor d'un objecte RAII pot donar lloc a resultats inesperats, Desreferència de punter nul : una desreferència de punter nul sovint provocarà una excepció o la finalització del programa a la majoria dels entorns, però pot causar corrupció en els nuclis del sistema operatiu o sistemes sense protecció de memòria o quan l'ús del punter nul implica un desplaçament gran o negatiu. En C++, com que desreferenciar un punter nul és un comportament no definit, les optimitzacions del compilador poden provocar que s'eliminin altres comprovacions, provocant vulnerabilitats en altres llocs del codi.
Algunes llistes també poden incloure condicions de carrera (lectures/escriptures simultànies a la memòria compartida) com a part de la seguretat de la memòria (per exemple, per al control d'accés). El llenguatge de programació Rust impedeix per defecte molts tipus de condicions de carrera basades en memòria, perquè assegura que hi hagi com a màxim un escriptor o un o més lectors. Molts altres llenguatges de programació, com ara Java, no impedeixen automàticament les condicions de carrera basades en la memòria, però encara es consideren llenguatges "segurs per a la memòria". Per tant, contrarestar les condicions de carrera generalment no es considera necessari perquè un llenguatge es consideri segur per a la memòria.
Referències
Categoria:Memòria informàtica