Secure Software Design
OpenSSL was initially developed in 1995 as a commercial-grade, open-source and fully featured toolkit for implementing Secure Socket Layer (SSL) and Transport Layer Security, and as a general-purpose cryptographic software library (Khan, 2015). It has grown over the last two plus decades as the pre-eminent secure protocol used in nearly all internet servers. Ironically, the maturity of the adoption did not translate into a mature code-base. It has grown to include a patchwork of quick-fixes, subordinate features (e.g. FISP 140-2) and excessive backwards compatibility support. Further, it is grossly underfunded relative to its adoption; the entire project operates on a budget of one million dollars per year (Yadron, 2014), and mostly funded through donations.
The intended mechanics of OpenSSL are quite simple and straightforward (figure 1). At a very high-level there are approximately six steps that involve; the server, the client and a 3rd party authentication authority who is trusted and referred to as the “Certificate Authority” and consists of two phases; an initial session initiation/handshake and a bulk data transfer. When a socket connection is established between the client and the server, the data is encrypted and de-encrypted using a synchronous mode of communication1. The standard release of OpenSSL is serial in nature, meaning it handles one connection within one context. From the point of view of cryptographic operations, the release is based on a synchronous/ blocking programming model.
Unfortunately, this seemingly straightforward solution to encrypting and ultimately securing data over the internet has significant flaws. These flaws have resulted in vulnerabilities that have compromised tens of millions of user accounts, email servers, bank transactions and immeasurable fear in the use of the internet. This paper will examine recent vulnerabilities, exploitations, principles, best practices as well as proposed testing and verification plans for future implementations for OpenSSL and likely replacements.
|
Since 1999, CVEdetails has tracked vulnerabilities for OpenSSL. There have been a total of 173; 92 (more than half) have occurred in just the last 3 years (CVEdetails, 2017). Design flaws are persistent in OpenSSL and have resulted in a growing number of identified vulnerabilities. Specifically; poor and inconsistent documentation, difficult to read formatting, complex coding practices and examples where the code is dependent on the properties of the data. As we will see in one of the examples below, not all flaws in OpenSSL fall in the category of a design flaw; implementation flaws are a category that can have major implications even in the most perfectly designed system.
How do these design flaws manifest themselves into vulnerabilities? The most notorious and recent examples of the OpenSSL vulnerabilities was the Heartbleed bug - CVE-2014-0160 (click here for a detailed description of Heartbleed). The naming of Heartbleed is based on Heartbeat, while the Heartbeat is an extension for the Transport Layer Security (TLS) and datagram Transport Layer Security (DTLS) protocols, it was proposed as a standard in 2012. When a socket connection between the client and the server is made, the default is to break the socket once the server completes its request. If the client needs to continue, a renegotiation is required. As a means to keep the socket open to avoid constant re-negotiation, heartbeat will keep the line open by sending a small (4-byte word) packet to the server. An acknowledgement is made by the server and the line stays open. One of the project’s authors (Robin Engelmann) submitted his code, it was reviewed by one of the four OpenSSL core developers and implemented.
Unfortunately, there was a bug in the code that was not identified by the developer, nor was it discovered by the reviewer. The bug allowed a 65K byte request to sneak in behind the 4-byte word packet on the Heartbeat. This exploit resulted in a memory leak. Specifically, the server was expecting a 4-byte word request, acknowledged it but responded by providing 64K bytes of information that was in its memory without encrypting the data. Thieved data elements included passwords, servers’ private keys and users’ session cookies.
This case is primarily an implementation flaw versus a design flaw and more specifically a flaw in procedure. There were only two individuals involved (reported); one who wrote the code and one who verified the code, yet the consequences were significant. |
If the memory accessible by the attacker can be effectively controlled, it may be possible to execute arbitrary code, as with a standard buffer overflow. If the attacker can overwrite a pointer's worth of memory (usually 32 or 64 bits), he can redirect a function pointer to his own malicious code. Even when the attacker can only modify a single byte arbitrary code execution can be possible. Sometimes this is because the same problem can be exploited repeatedly to the same effect. Other times it is because the attacker can overwrite security-critical application-specific data -- such as a flag indicating whether the user is an administrator. See figure 2 for an example of “bad code” in C. This example takes an IP address from a user, verifies that it is well formed and then looks up the host name and copies it into a buffer.
This function allocates a buffer of 64 bytes to store the hostname, however, there is no guarantee that the hostname will not be larger than 64 bytes. If an attacker specifies an address which resolves to a very large hostname, then we may overwrite sensitive data or relinquish flow control to the attacker. Note, this example also contains an unchecked return value that can lead to a null pointer deference.
|
OpenSSL is burdened with years of legacy code that are difficult to maintain and keep up to date. OpenSSL requires porting to many platforms, which can cost your team both time and money.
Certificate Costs – There are different types of certificates that are available to purchase for a site depending on needs. The Certificates also need to be renewed, yearly or monthly, depending on preference. Self-signed certificates are available but they are not recommended and may not offer all the advantages of a certified and paid for Certificate.
Mixed Modes – If the SSL Certificate is not setup correctly and/or the site still serves pages and files via HTTP (non-encrypted), then the site will show a warning to visitors saying that the site is not fully secure. This can make visitors wary about browsing the site or using services.
Server Resources –Modern Servers have improved and so have the Libraries (For Example OpenSSL) fixing many inefficiencies. If running a server from several years ago then this may be an Issue, otherwise, it is not seen as a reason to not use HTTPS
Ensuring the confidentiality, integrity and availability of data and a system requires principles are established at the beginning of the development cycle and is engendered throughout the organization’s culture. Further it is not a one-and-done process, it is a continuous cycle. The following nine design principles (see figure 3) have been developed by the Open Web Application Security Project (OWASP) with examples.
Design Principle |
Definition |
Example |
Apply
defense in depth |
This is based on a
defense-in-depth approach where a single breach does not affect the entire
system. This does add complexity but a
layered security model eliminates the risk of compromising an entire system
from a single attack vector. |
A cloud-based application to
enable vendors to update their Purchase orders and delivery status must be
strictly limited to their access and not have untethered access to the
overall ERP system. (Target breach). |
Use a
positive security model |
A security model referred to as a “whitelist” is one that
defines what is allowed and rejects everything else. |
When performing input validation, the positive model
dictates that you should specify the characteristics of the allowed input, versus
trying to filter out the bad. |
Fail
securely |
Make sure that any system you
design does not fail "open." |
If a user fails to enter his login
credentials correctly after three attempts, the user will be locked-out from
logging in and will be required to discuss with a human for a password reset |
Run with
least privilege |
When granting privileges to users, grant them the least
privilege necessary to perform their job function |
Rarely would a general user need root level access to a
system, therefore restrict access as a default and escalate as an exception |
Avoid
security by obscurity |
System security should not depend
on the secrecy of the implementation or its components |
PGP encryption is (or was) a
military grade cryptosystem is publicly available source code. Just by knowing the source code of PGP does
not necessarily provide an advantage for an attacker |
Keep
security simple |
The more complex the code, the greater the attack surface
– KISS principle |
Developers should avoid double negatives and complex
architectures when a simpler approach is better. OpenSSL is notorious for violating this tenet. The code is overly complex and therefore
limits the population of qualified individuals to develop it further. |
Detect
Intrusions |
Detecting intrusions is important
because otherwise you give the attacker unlimited time to perfect an attack Detecting intrusions
requires three elements: ·
the capability to log security-relevant events ·
procedures to ensure the logs are monitored regularly ·
procedures to properly respond to an intrusion once detected |
Cryptographic control flow
integrity (CFI) checks. Small pieces
of code embedded within the overall source code to check for integrity upon
function and subroutine calls. |
Don’t
trust infrastructure |
While market standard servers are written with security in
mind, the actual application’s security is the responsibility of the
application team |
every application needs to authenticate and authorize every
action from surrounded systems |
Don’t
trust services |
implicit trust of externally run systems is
not warranted. All external systems should be treated in a similar fashion |
a loyalty program provider provides data that
is used by Internet Banking, providing the number of reward points and a
small list of potential redemption items. However, the data should be checked
to ensure that it is safe to display to end users, and that the reward points
are a positive number, and not improbably large |
Establish
secure defaults |
by default, the experience should be secure, and it should
be up to the user to reduce their security – if they are allowed |
By default, password aging should be enabled (after 12
weeks, it is required to change your password). If allowed, tis can be
disabled but only through elevated permissions. |
Could automated testing have prevented some of the vulnerabilities within OpenSSL like Heartbleed? Looking at Heartbleed specifically, it was in fact a code review performed by a company in Finland, Codenomicon in 2014, three years after the source code was implemented. Although the bug existed in the open source code for a long time, most widely-used static analysis tools were not able to find the vulnerability and dynamic analysis did not identify the problem because they cannot fully test any program in human-relevant timetables.
Comprehensive software testing protocols could have identified the problem sooner. Heartbleed could potentially have been identified by fuzz testing, which is a process that involves generating pseudo-random inputs and sending the inputs to the program in order to see if something undesirable occurs. Thorough negative testing in test cases may also have been a potential solution for identifying the vulnerability (etesting, 2014). Other potential approaches to testing the open source software that could have made a difference include context-configured source code weakness analyzers; 100 percent branch coverage of alternative implementations; and aggressive run-time assertions.
What are Safe Alternatives to OpenSSL?
The Heartbleed bug brought a lot of attention to the systemic issues in the OpenSSL project, two initiatives have been underway; LibreSSL and BoringSSL by Google. These projects are currently at varying levels of maturity and capabilities.
Google developed a fork dubbed BoringSSL that addresses the specific needs of Google and Android. This was in response to their ongoing patchwork of OpenSSL. Specifically, their portfolio of products continued to grow and OpenSSL was too difficult to rely on for backwards compatibility. This is not intended for general purpose use as Google claims the API’s and ABI’s may not be stable and could create a lot of frustration for developers who are familiar with OpenSSL. BoringSSL does not have a stable API or ABI. It must be updated with its consumers. It is not suitable for, say, a system library in a traditional Linux distribution. For instance, Chromium statically links the specific revision of BoringSSL it was built against. Likewise, Android's system-internal copy of BoringSSL is not exposed by the NDK and must not be used by third-party applications (googlesource, 2017).
LibreSSL on the other hand is a fork that is intended for broad use with a few exceptions. LibreSSL is a fork developed by the OpenBSD team and follows the security guidelines used elsewhere in the OpenBSD project. Within the first week of the team’s work, they immediately removed 90,000 lines of source code. Additionally, they removed support for FIPS standards, claiming that “FIPS mode isn’t just worthless, it’s actively harmful” (De Raadt, 2014). In terms of adoptions, LibreSSL is now the default provider of TLS for Alpine Linux, Dragonfly BSD, HardenedBSD, Morpheus Linux and a number of others. Under the code-base, several capabilities that were available in OpenSSL have been removed; Heartbeat functionality was one of the first to be removed and support for platforms that no longer exist (NetWare for e.g.). LibreSSL does not carry much of the overhead of OpenSSL and it already seeing penetration as the preferred provider for TLS.
The internet now has three options for securing traffic, security teams will need to evaluate their specific requirements in order to select the right path.
Conclusion
Defects in code is an inevitable fact of software development. Unfortunately, with the massive adoption of mobile devices and SaaS providers, a single vulnerability can amplify itself much faster and broader than in the past. Infrastructure tools like OpenSSL are particularly vulnerable and highly attractive targets. This means that organizations will be required to invest and allocate additional investment towards securing the confidentiality, integrity and availability of their applications and user’s data. An increasing level of investment in secure software development will now be table-stakes.
Organizations will need to find the right balance of features in the product versus security. Given the number of unused features in most software applications, there could be a trend to scale-down the feature set to the minimum viable product (MVP) in order to provide a product that is more secure.
Khan, F. (2015, October 21). LibreSSL: The Secure OpenSSL Alternative. Retrieved April 29, 2017, from http://resources.infosecinstitute.com/libressl-the-secure-openssl-alternative/
Ristic, I., & Kandek, W. (2012). RSA Conference 2012. In SSL and Browsers: The Pillars of Broken Security. Retrieved April 29, 2017, from http://resources.infosecinstitute.com/libressl-the-secure-openssl-alternative/
Cheng, E. (2012, February 08). An Introduction to Mutual SSL Authentication. Retrieved April 30, 2017, from https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication
Yadron, D. (2014, April 11). Internet Security Relies on a Very Few. Retrieved April 30, 2017.
Intel® QuickAssist Technology: Get Started. (2012). Retrieved April 30, 2017, from http://www.intel.com/content/www/us/en/embedded/technology/quickassist/overview.html
Openssl » Openssl : Vulnerability Statistics. (n.d.). Retrieved April 30, 2017, from http://www.cvedetails.com/product/383/Openssl-Openssl.html?vendor_id=217
Software Testing, Heartbleed & Open Source Software | E-testing. (2014, August 12). Retrieved April 30, 2017, from https://www.etesting.com/2014/08/12/heartbleed-and-the-testing-of-open-source-software/
Święcki, R. (2016, September 23). Fix Use After Free for large message sizes (CVE-2016-6309). Retrieved April 30, 2017, from https://www.openssl.org/news/secadv/20160926.txt
Some proven application security principles, OWASP. (2015, July 29). Retrieved April 30, 2017, from https://www.owasp.org/index.php/Category:Principle
Porting from OpenSSL to BoringSSL. (n.d.). Retrieved May 01, 2017, from https://boringssl.googlesource.com/boringssl/ /HEAD/PORTING.md
De Raadt, T., The future (or lack thereof) of LibreSSL's FIPS Object Module. (2014, April 22). Retrieved May 01, 2017, from http://opensslrampage.org/post/83555615721/the-future-or-lack-thereof-of-libressls-fips