- The memory is one of the most important part of computer;
- 70% of vulnerabilities patched by Microsoft are related to bad memory management in software development;
- Memory corruption is very convenient for attacker as it is fileless attacks limiting the capacity of cyberdefense to investigate disruptive events;
- Software protection against memory exploitation is software themselves and can be subject to bypass or logical attacks;
- Hardware protection against memory exploitation is gaining in popularity and ARM announce its secure Morello ship for the end of 2021.
Computerized systems are everywhere. Phones, automotive, power plant, pacemaker. They may all have design weaknesses that may be weaponized to perform a cyberattack. According to Microsoft, among all the patched vulnerabilities since 2006, 70% of them are dealing with software’s volatile memory management. Memory Exploitation is then not only a vulnerability but a Risk in itself.
The volatile memory (RAM) is a central part of computers. It allows to buffer the instruction that a processor, holding the arithmetical logics, needs to compute. It contains the various information necessary to run the Operating System or a program. A computer cannot work without a memory.
Overflowing the memory can lead to two mains effects on a targeted machine:
- Denial of Service (DOS): a program is shut down;
- Arbitrary Code Execution (ACE): injection then execution of a program.
If DOS attacks are generally used for sabotage purpose, ACE attacks are the root of further adversarial actions. It is an opportunity for an intruder to infiltrate a network, inject its tools in a computer and achieve high privilege on the infected computer. Some ransomware attacks leverage this type of vulnerability.
When performing an attack, the intruder always must find ways to send its own malicious instruction to the target, take control of it and access resources normally out of his hands. As software is one of the key aspects of digitalization and memory exploitation represent more than half of their vulnerabilities, it is essential that technical C-Level and development staff understand this type of undesirable behavior and mitigate them.
Overview of Volatile Memory and Buffer Overflow Attacks
Computer memories are designed like a table where you allocate cells to receive a kind of information (instruction or data). But if the software does not check that the user input length is smaller or equal to the buffer size, the overflowing data will erase the following cells, causing either a crash or the execution of unintended instruction by inserting a well-placed pointer. Pointers are an indication for the processor of which cell is the next starting point of the series of instruction it must perform.
One of the big advantages for the attacker to use this kind of vulnerability is that Buffer Overflow are classified as fileless attacks, meaning that the injected code will reside only in memory. One of the main sources of information for Digital Forensic and Incident Response specialist are data stored in persistent memory (ROM). Unlike data stored in the ROM, data stored in the volatile memory (RAM) do not survive a machine shutdown and may even be erased as soon as the exploited software stop running, leaving absolutely no trace of the attack or the injected instruction.
There are four main types of memory attacks:
- Code Corruption: overwriting legitimate code to insert a malicious pointer to the malicious code. It is one of the most basic type of attacks.
- Control Flow Execution or Return Oriented Programming (ROP): this type of attack is used when the software protects its code by checking its integrity against overwriting. The attacker will scan how the software jump from one section of the code to another and will change the memory address at the end of an instruction block by the memory address of the malicious code. This works because as the final memory address change at every execution and is attributed by the Operating System. As it is not hardcoded in the software for obvious reason, the integrity check skip the memory address. Return to the C Library (Ret2Libc) is a variant of the ROP.
- Data-only attacks: Code Corruption and Control Flow execution are resulting from a code injection. But it is possible to attack a software without it, as software design may allow to bypass security measures. For example, if in memory you have “administrator=False”, you overwrite “False” with “True” and you achieve administrative privilege.
- Memory Leak: This technique works when a software is not cleaning the allocated memory spaces that are not used anymore. By crashing the application, the attacker can collect precious information about the software execution, gather insight about the security checks and found a way to bypass them.
This description may be a bit technical. This is yet remarkably similar to classical physical intrusion, scam technics or social engineering.
Code corruption is like you walking into the corridor of an airport in a foreign country, trying to exchange your cash for local money. If you ask a legitimate and honest citizen (the Operating System) he or she will give you the location of the Exchange Office. If instead you ask a scammer, he will point you to some random office where an insider accomplice is waiting for you to exchange your money at crazy rate with crazy fees.
Control flow execution is a bit trickier for the scammer. So, you get out of the plain, you ask a flight attendant how to find the exchange and tell you to follow the signpost that will lead you to the Exchange Office. But a scammer crafted a fake sign and replace the legitimate one to control the flow of passenger that want to exchange money. The scammer directs them to some random office where an insider accomplice is waiting for you to exchange your money at crazy rate with crazy fees. Ret2Libc would work very similarly.
Data-only attacks would be for the scammer to replace the exchanger officer in the exchange office.
Finally, Memory Leak would be like being in the lobby of a company and trigger the fire alarm (“the crash”). Because of fire safety rules, most of physical security (such as electronically locked doors, turnstile, …) are disabled. While everyone is leaving the building in panic, you are free to sneak into the offices, locating the security devices, accessing to all documents left on desks, to unlocked bureau
Software protection against Buffer Overflow
As soon as the first memory exploitation Proof of Concept came into light, software countermeasures have been invented. One of the earliest one, called canary, was inspired by coal mine safety.
One of the life issues that arise in coal mine was the amount of toxic gas, like carbon monoxide, that accumulate in the confined underground space. The idea was to use warm blood animal, like domestic canary, as early-warning of intoxication risks as the bird would be more sensitive than human. Miners or safety officer would check the vitality of the canary and in case of issue would evacuate or order to wear protective respirators.
The very same principle applies for computer memory protection. Canary, small pieces of benign data are placed at specific spot in the memory. You just must check that the canary has not been overwritten to prevent memory overflow. Those canaries were placed before “return” function, the legitimate direction sign in our previous metaphor. StackGuard was a precursor in this domain. Nowadays, this technology is included by design in language compiler like GCC or Clang.
But as you may notice, the canaries were always on the same spot. Knowing that you have always one before a return function, you can easily avoid erasing them. You can also reveal their presence with memory leak attacks, that would tell the attacker the structure of the code loaded in memory, like if he has a building map with indication of security cameras or metal detectors.
The next step was then to randomize the location of canaries. It is a process called Address Space Layout Randomization (ASLR). The counterattack was then to exhaustively search for their location with a brute force attack. Some additional protection, like PointGuard, use encryption to check the integrity of pointers (a “direction sign”). Other would create a read-only Return Address Repositoty (RAR) that store those memory addresses in a way that is impossible to overwrite. All those protections are generally now directly included in the compilation process – the process of translating a programming language into machine language (binary code).
A second classes of protection happened after a first compilation. It is use when you have a binary code and not the source code. This is especially useful for large companies that have a lot of legacy code and legacy systems. It would be too costly to securely redesign from scratch. The protective program would first decompile the binary code – transforming the machine language into a human readable programming language – then add a protection like a Return Address Repository, and finally compiled it back. Those types of protection, called Return Address Defender (RAD), are effective against Return Oriented Programming (ROP) attacks.
The problem of those post-compilation defender is that they require the programs to be paused, and some companies cannot afford such a procedure. This is particularly true for Web Services. To answer this, a third class of protection are called Run-Time Protection and brings a live supervision of inputs in the software to stop memory attacks. SafeStack or Sigfree are such solutions. The idea is to use a virtualized version of the memory and create a shadow application, a digital twin of the software. Inputs will be tested to see if it generates faults or error thanks to pattern recognition (Regular Expression, Regex). Web Application Firewall (WAF) are based on this type of methods to protect live Web Application.
In recent years software services moved from a host-based installation and access to a Web-based usage thanks to cloud. Runtime protection solutions became then essential to the defender toolbox. They are also more and more scrutinize by adversaries. But all these software protectors are themselves software. Relying only on logical protection to protect the protectors would be an endless loop. This is where hardware memory protection efforts find their relevance.
Hardware protection against Buffer Overflow
In the 1970’s and the 1980’s, there was only two memory management architectures systems : Memory Management Unit (MMU) and Capability-based systems.
MMU were the first to be introduced and are still today the one in use. It is a solution that controls the access that a processor – that is doing calculation – do on the memory – that store the data to be processed. Basically, the MMU ensure that one program cannot access the memory space reserved for another program. Each memory space is delimited with boundary addresses.
Capability-based systems is a set of keys, the capabilities. Each key is associated with a set of access rights. When a user program starts, it gets an associated key with the principle of least privilege: it has access only to the information and resources needed for its legitimate purpose. Capability-based systems are reputed more secure as they defined more security features and enforce more control measures.
Capability-based systems were costlier to build and have been put aside. But in the 2010’s, computer and its memory became more exposed. Governments research programs and big corporations unleashed money into projects aimed to design more secure physical memory management systems. Once such system is the Capability Hardware Enhanced RISC Instructions (CHERI) project led by the University of Cambridge and supported by the United States Defense Advanced Research Project Agency (DARPA).
CHERI offers the security level of capability-based systems and the ability to be transposed into any hardware architecture, including existing MMU. The company ARM, famous for its low-consumption processors, are engaged in the CHERI project. By the end of 2021, they promise that their new Morello ships will reduce the opportunities of any memory vulnerability and exploitation (Buffer Overflow, ROP, …) by 70%.
For any engineer, its is hard to accept that what is building has flaws. Yet when it comes to software and memory management, the only possibility to avoid or reduce those flaws by design seemed to be shifting all its codebase to language like Go or Rust that manage memory by themself. But they have truly little power when it comes to hardware or underlying Operating Systems.
The quick solution would be to add additional layers of software that will mitigate those risks. But they are limited, they can be bypassed or worth, they can be compromised. In security and risk management, the same principle applies every time:
- Treat problems the most uphill possible;
- Do not introduce new weakness to mitigate another one.
When it comes to computer, applying these principles means dealing at the end with the hardware level.
The beauty of computer science and the informatics revolution is that a permissive hardware allows to build architecture for tools that we do not even now that they will exist, thanks to the software paradigm. A set of tools that we can repurpose almost indefinitely without touching the physical architecture, apart for punctual performance improvement. From an engineering and an evolutionary historical point of view, this is groundbreaking.
The idea of hardware security is not to switch to a non-permissive physical architecture, that would break the steam of computer technologies. But after nearly half a century of use, we have some perspective of what is needed, what could be useful and what is undoubtfully dangerous. Smart systems and cyber-physical systems are for sure a key component of the next two decades. And their flaws cannot eternally be bound to additional onion-like layers of software protection. This hardware security uphill movement will for sure brings more serenity to software development but will also require more anticipation to foresee threats’ adaptation strategy.
- Matt Miller (Microsoft Security Response Center). Trends, challenge, and shifts in software vulnerability mitigation. Black Hat Israel. February 2019
- SZEKERES, Laszlo, PAYER, Mathias, WEI, Tao, et al. Sok: Eternal war in memory. In : 2013 IEEE Symposium on Security and Privacy. IEEE, 2013. p. 48-62.
- COWAN, Crispan, PU, Calton, MAIER, Dave, et al. Stackguard: automatic adaptive detection and prevention of buffer-overflow attacks. In : USENIX security symposium. 1998. p. 63-78.
- SHACHAM, Hovav, PAGE, Matthew, PFAFF, Ben, et al. On the effectiveness of address-space randomization. In : Proceedings of the 11th ACM conference on Computer and communications security. 2004. p. 298-307.
- COWAN, Crispin, BEATTIE, Steve, JOHANSEN, John, et al. PointGuardTM: Protecting pointers from buffer overflow vulnerabilities. In : Proceedings of the 12th conference on USENIX Security Symposium. 2003. p. 91-104.
- CHEN, Gang, JIN, Hai, ZOU, Deqing, et al. Safestack: Automatically patching stack-based buffer overflow vulnerabilities. IEEE Transactions on Dependable and Secure Computing, 2013, vol. 10, no 6, p. 368-379.
- John Fu (BlackBerry), Memory-Based Attacks are on the Rise: How to Stop Them. June 2018.
- WOODRUFF, Jonathan, WATSON, Robert NM, CHISNALL, David, et al. The CHERI capability model: Revisiting RISC in an age of risk. In : 2014 ACM/IEEE 41st International Symposium on Computer Architecture (ISCA). IEEE, 2014. p. 457-468.