The OpenSSL Crises
Anyone interested in cybersecurity will have noticed the newly discovered vulnerability in OpenSSL. The initial panic seems to have passed now, but only a few days ago the alarm bell was ringing loudly with advice bouncing around the internet on the best ways to contain this problem. But this initial panic was well placed. The discovered vulnerabilities included a “stack buffer overflow that could trigger crashes or lead to remote code execution”
What does that mean? Essentially, in a worst case scenario. it means someone can start running arbitrary programs – essentially “take control of your machine” from anywhere on the internet. Now because OpenSSL can be found on so many computers (client and server) the consequences could be catastrophic.
So it turns out, this time, it wasn’t so bad. The flaw has now been downgraded from “critical” to “high”. Yes the memory flaw is there, but it seems it’s harder to fully exploit than first thought. So far, so good…
But we shouldn’t get complacent. The type of programming flaws that this vulnerability is based on are everywhere; we just haven’t found them all – and likely never will. And there’s a lot of code out there (not just OpenSSL) in which these problems are hiding.
The Secure Network by Design project, is helping to stop the perpetual cycle of incident-panic-mitigation working with technology providers through to end users.
Understanding the problem
So what exactly is happening here? Memory based attacks have been around as long as computers have existed. As a programmer I start with an “intent”: a desire to make something happen on a computer. I express this intent in a set of instructions; typically a human readable programming language. And these human readable instructions get converted (though a convoluted compilation and real time optimisation process) into a set of machine readable instructions that are executed on the computer’s CPU.
But here’s the problem: it’s not a perfect process. The language I use as a programmer to express my intent is clumsy, and I as the programmer make mistakes when I express my intent (a bug). Also the process by which programming instructions can be converted into machine instructions is error prone. The net effect: bugs are introduced where the end program is not doing exactly what I intended. And where these unintended errors allow a piece of code written to do one thing, affect another piece of code intended to do another thing, we have the most insidious of vulnerabilities. Most of the time this is a scoping or memory vulnerability. A devious attacker can exploit this vulnerability, and by massaging the data, encouraging the computer to run over its intended scope and do a thing it was never intended to do. This is known as a remote code execution (RCE) vulnerability; one of the most devastating forms of attack.
Secure by Design
So how do we solve this problem? The ethos behind the secure by design philosophy, is to make it much harder to create these issues in the first place – by design. It provides us methods to better capture and express our intent as a programmer, and to enforce these intents when the program runs. The CHERI technology (Capability Hardware Enhanced RISC Instructions) developed in a collaboration led by University of Cambridge, has been looking at this problem for some time. More recently these principles have been embodied in a prototype chip design from ARM called Morello. This new technology should make memory vulnerabilities, like the recent OpenSSL crises, much harder to create.
Secure Networking by Design
NquiringMinds, University of Oxford and the Techworks, are collaborating on this CHERI/Morello initiative, but taking a narrower focus: looking at the problem primarily from a network perspective.
And the reason we take this focus is the same reason the world panicked when the new OpenSSL vulnerabilities were announced. Network based vulnerabilities are arguably the most difficult to manage and the hardest to contain. They can be launched at scale and speed, replicating themselves as they jump from node to node. Network based vulnerabilities are a hyper scaling threat which need laser focus if we wish to properly contain them. Conversely, detecting and calibrating these threats remotely and across the network, is the most practical way of containing the problem.
Proving it works – Threat containment
So enough of the background, why is this actually relevant? The theory is simple: OpenSSL CVE-2022-3602 is a memory based vulnerability; CHERI/Morello is a technology that is intended to limit the impact of memory based vulnerabilities. But does it work?
What we have done is really quite simple.
We have taken a proof of consent vulnerability exploit kindly shared by DataDog [1]. This is example code which concretely demonstrates how the disclosed vulnerability can be exploited.
We have created three systems, housing the vulnerable code. Specifically these systems all use OpenSSL v 3.02 (one of the versions known to be vulnerable.) And it has been created in three flavours:
- CheriBSD on ARM Morello with OpenSSL in hybrid mode (interpreted with respect to a global default data capability model [2] – essentially a legacy aarch64 binary)
- CheriBSD on ARM morello with openSSL in purecap mode (every pointer is using capabilities [2])
- Desktop PC with Ubuntu 22.04 – for comparison
Example detailed tests are available here [3].
As presented in [1] for each of the above scenarios we open two instances of OpenSSL in client and server modes, respectively. We assume the client to be the malicious entity. First, the client creates a certificate specially crafted to take advantage of the vulnerability. Second, it initiates a TLS connection with the server.
In the ordinary OpenSSL implementation on Ubuntu 22.04 — case (c) above — the TLS negotiation initiated by the client proceeded without any errors in both the server and the client. So, a malicious client would be able to mount its attack without detection.
In the CheriBSD running OpenSSL in purecap mode — case (b) above — the OpenSSL server crashed due to a protection violation error, i.e., a capability bounds fault. An example run using the gdb is provided in the github repo [3]. The all important error is trigged as below
Program received signal SIGPROT, CHERI protection violationCapability bounds fault.
As can be seen from the above example run the culprit is the ossl_punycode_decode function which produces a buffer overflow on a specially crafted input i.e., the malicious certificate authority.
In the CheriBSD running OpenSSL in hybrid mode case (a) above — no such protection was seen i.e., the OpenSSL server did not exhibit a buffer overflow violation.
What this means is: if you built your application/server/device using these secure by design principles, when the next OpenSSL-like vulnerability gets announced you won’t be looking as panicked as everyone else. More importantly, your users will be safer and the threat won’t spread as far or as wide.
We still have a long way to go. The technology is still in its infancy. The distribution of commercial chips and operating systems containing this technology are still some way from the market. But clearly, solving this memory-safety problem “by design”, rather than a perpetual cycle of incident-panic-mitigation, is better for everyone: technology providers through to end users.
Vulnerabilities of this nature will continue to hit the headlines. Through our early work we have demonstrated the value of a CHERI based system on a real, contemporary problem. We expect this to continue and as we acquire more use-case examples the argument for implementing this technology “by default” becomes self-justifiable.
Alex Mereacre & Nick Allott – NquiringMinds. www.nquringminds.com
[2] https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-941.pdf
[3] https://github.com/nqminds/morello-docs
Getting involved
If you want access to a Morello board to run your own experiments
https://www.dsbd.tech/get-involved/morello-board-request/