Error: Safety security both

A simple error: Safety, security or both?

Aside from safety properties, can we use static analysis tools to detect security issues? Yes, as we will show by discussing a programming error in uftpd, an ftp server implemented in C. In particular, we will show how the error influences both safety as well as security and under which conditions it can be exploited. Furthermore, we will give a quick glance at techniques used to minimize the issue’s impact or to avoid this and comparable errors from the get go.

Recap: Safety vs. security

Safety (more precisely: functional safety, in the sense of ISO/IEC 61508, ISO 26262, and other derived standards) refers to the protection from errors or malfunctions, in particular with respect to dangers or risks of injury, loss of live or property or other undesired outcomes.

Several programming standards defining safety conditions and how to appropriately develop software and systems exist. An example prominently used in the automotive industry, the MISRA C software development guidelines were introduced in 1998 and have been updated several times since.

In contrast to functional safety, software security is more focused on deliberate actions explicitly targeted at providing harm. Rather than asking whether a system can cause harm due to a malfunction, security considerations deal with the question whether an attacker can make a system cause harm. Again, different coding guidelines for the avoidance of security issues are available. For instance, the SEI CERT C Coding Standard aims at safety, reliability and security simultaneously. With the ISO/IEC TS 17961:2013 an international norm for the development of security-critical software has been established.

As we will show below, software flaws often have both a safety as well as a security aspect. Accordingly, the aforementioned standards link to each other in various places and are interconnected. For several of them, mappings from one to another are provided. Safety standards such as the MISRA guidelines have taken up security aspects as well and vice-versa.

Example: CVE-2020-5204

Context

Our issue can be found as CVE-2020-5204 in common vulnerability databases such as vulndb. The issue has initially been discovered by Aaron Esau. It resides in the part of uftpd responsible for handling the PORT command of the file transfer protocol (FTP). The PORT command is send by the client to the server to make it open a reverse connection to the client. The client can then use this connection to transfer files.

To allow the server to connect back to them, clients need to provide an IP address and a port number. As FTP is a cleartext protocol, the client simply sends a string formatted as follows: PORT(ip1,ip2,ip3,ip4,port1,port2). The server then uses ip1 to ip4 as the four groups of an IPv4 IP address and calculates the port to connect to as port = (port1 * 256) + port2.

The issue

Following, let’s have a look at how uftpd used to extract the IP address from the given user command. Before the maintainers fixed the issue, the code looked as follows:

cve-2020-5204 error in safety and security

The parameters ip1,ip2,ip3,ip4,port1,port2 extracted from the command send by the client reside in strINET_ADDRSTRLEN is equal to 16, which is large enough to store an IPv4 address. Three bytes are used per group (each containing one to three digits). Three additional bytes are used for the dots and the null terminator. Using sscanf, the six numbers are extracted from str and stored in individual integer variables. Afterwards, sprintf is used to recombine them into a string properly representing an IP address. However, sprintf does not check the size of the buffer it writes to in any way! In consequence, if the client provides numbers which are too large, sprintf will write more than what can be stored in addr. Anything following addr on the stack will be overwritten, resulting in a classic stack buffer overflow.

Impact to safety and security

To examine the impact of the issue, we have extracted the code shown above into a simple example application. If executed with number in valid ranges, the application behaves as expected:

Once one of the parameters is too large, sprintf overwrites and thus replaces parts of the stack, preventing execution from continuing properly:

The program terminates immediately, which would be unacceptable for any safety critical component. Furthermore, when it comes to security, an attacker can use the buffer overflow to overwrite parts of the stack. In particular, anybody able to connect can overwrite the return address. Ultimately, this could lead to an attacker gaining control over the uftpd process and potentially allow execution of arbitrary code.

Luckily, because of the %d in the format strings of both sscanf and sprintf, the buffer and thus the rest of the stack can only be overwritten by characters occurring in numbers: the numerals 0 to 9 and the -. In consequence, an attacker cannot overwrite the return address arbitrarily, diminishing the potential impact of an attack.

The bugfix

To prevent the buffer overflow in the first place, sprintf was replaced by snprintf, which requires the caller to provide a maximum size to write and thus prevents overwriting:

error bugfix

Mitigation and avoidance

Stack buffer overflows are a very common issue. The Common Weakness Enumeration lists them in their list of the Top 25 Most Dangerous Software Weaknesses. Buffer Overflows have been responsible for some of the most prominent issues, with impacts ranging from databases to warships. In consequence, different techniques for their avoidance have been developed.

Stack canaries and randomization

The idea behind a stack canary is to place a random integer on the stack just before the return pointer. When using a buffer overflow to replace the pointer to gain control over the process, the canary is overwritten as well. Before a routine actually returns, the canary is verified. If it has been changed, the systems knows an overflow has occurred and stops execution.

With randomization, the address space used by an application is ordered and allocated more randomly. This effectively makes it harder to exploit a buffer overflow with malicious intent. Again, the possible security impact is reduced but the application still crashes.

Static analysis tools

Static analysis tools can detect the potential stack buffer overflow in our example during the implementation phase. This allows developers to replace any offending calls with better alternatives. In particular, for our example, generic description of the tool, as the Axivion Suite, offers several rule sets that would have uncovered the issue:

References and further information

  • [cert] SEI CERT C Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems (2016 Edition)
  • [iso17961] CAN/CSA-ISO/IEC TS 17961:2018-01-01, Programming languages, their environments and system software interfaces – C secure coding rules
  • Software quality is not a myth: Real examples

Share:

Share on linkedin
Share on twitter
Share on whatsapp

Leave a Comment

Related Posts

Improving test efficiency
John Paliotta

Improving test efficiency

Effective software teams are always looking for ways to make their members more efficient. They realize that improving the development process is an good way

Debugging without Security risks
Niroshan Rajadurai

Debugging without security risks

Security researcher Michael Myng found the keylogging code in software drivers that were preinstalled on HP laptops to make the keyboard work. He discovered the

Hey there!

Subscribe and get an email every time we’ve got a new quality piece on here.