Helping Embedded Developers Code More Securely: banned.h and strsafe

April 30, 2019

Windows developers may be familiar with “banned.h” or “strsafe” libraries. Introducing safe libraries to development is nothing new, as was covered in the 2007 presentation on SDL for Windows Vista (slide 7). While basic, these basic libraries have been shown to provide significant value - as discussed later in the deck, 41% of bugs that Microsoft removed in Vista early on were due to removal of ‘banned’ API function calls.

To date, we do not know of an open-source project applying these same principles to the embedded development community. That is why we’re releasing an open source embedded-focused banned.h library, available on GitHub.

Using this library, embedded systems developers can include this header file to help them and their colleagues: - Avoid functions which are known to commonly lead to vulnerabilities - Utilize functions designed to help developers be more explicit about their desired behavior - Utilize functions that return error codes indicating what the function did in edge cases - Reduce time spent reviewing and fixing buffer handling issues during development

It is still important for developers to use this library correctly, and to know that it only helps reduce memory corruption issues. Other types of security vulnerabilities are outside the scope of what it aims to protect against. A developer must correctly select the length of the memory they have allocated, and should check error codes.

If you’re reading this, you may think “well, if I know to set the length, I can use strncpy instead of strcpy!“. That’s a good step in the right direction, but using this library you will find that these “n” variants are sometimes banned because they are tough to call correctly. As Microsoft learned when making the original banned.h, there are numerous errors observed when people call those. The replacement functions attempt alleviate some issues such as how the default “n” functions can fail to prevent null-termination on overflowed buffers and will not return an error code on overflow.

Let’s look at an example, which is perhaps the simplest possible use-case for this header. In this scenario, a busy developer has written the following code:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main(int argc, char *argv[])
{ 
	// For this example, pretend that this is a security sensitive value:
	int other_value = 2;
	// Reserve 5 byte of buffer plus the terminating NULL. 
	// should allocate 8 bytes = 2 double words, 
	// To overflow, need more than 8 bytes... 
	char buffer[5];

	char input[10] = "123456789"; //plus a null terminating byte
	printf("Original other value= %d\n", other_value);
	printf("Source buffer content= %s\n", input);

	// Copy the user input to buffer, without any bound checking.
	// This shows the insecure behavior:
	strcpy(buffer, input);
	printf("Destination buffer content= %s\n", buffer);
	printf("Final other value= %d\n", other_value);

	if (other_value != 2) {
		// Do something unsafe, such as grant the user admin access...
	}
	return 0; 
} 

As you can see, the developer has an issue as input (which, let’s pretend, is attacker controlled and is not hardcoded). This input overflows the destination buffer that it is copied to. By adding one line, and compiling, the program will refuse to compile:

#include "banned.h"

For those of you working with a new code-base, this may be fine – but adding it to an older code-base would be a non-starter. To help with this, we introduce a definition EMBD_STRSAFE_WARN_ONLY which can be set at the compiler level to instead receive instructional warnings:

overflow.c:32:3: warning: 'strcpy' is deprecated: This function isn't considered secure. [-Wdeprecated-declarations]
                strcpy(buffer, input);
                ^~~~~~
                strncpy_strsafe
...

The objective is to ask developers to change to more secure function variants, and make them aware of the potential issues right in their development process. Our opinion is that a static source-code analyzer (often run later or down the chain, if it is run at all due to the cost of such solutions) shouldn’t be the first time that developers learn about an unsafe function being used. If the developer looks at the warning above, they may choose to update their code to this, which will be a safer variant:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include "banned.h"

int main(int argc, char *argv[])
{ 
	// For this example, pretend that this is a security sensitive value:
	int other_value = 2;
	// Reserve 5 byte of buffer plus the terminating NULL. 
	// should allocate 8 bytes = 2 double words, 
	// To overflow, need more than 8 bytes... 
	char buffer[5];

	char input[10] = "123456789"; //plus a null terminating byte
	printf("Original other value= %d\n", other_value);
	printf("Source buffer content= %s\n", input);

	// Copy the user input to buffer, with bound checking.
	// TODO: Check return code and handle:
	strncpy_strsafe(buffer, 5, input);
	printf("Destination buffer content= %s\n", buffer);
	printf("Final other value= %d\n", other_value);

	if (other_value != 2) {
		// Do something, such as grant the user admin access...
	}
	return 0; 
}

Running this, the developer should see that the string will be safely truncated and terminated with a null byte. The developer still needs to think about the “logic bug” issues, such as ensuring that the truncation of the value in the destination buffer doesn’t change it’s meaning (e.g. if it is being used as a value to compare against and shouldn’t be truncated). However, the strncpy_strsafe takes care to return error codes that can be checked to indicate when this happens, specifically returning STRSAFE_E_INSUFFICIENT_BUFFER in this case.

$ ./overflow_fixed
Original other value= 2
Source buffer content= 123456789
Destination buffer content= 1234
Final other value= 2

We’ve developed this as a result of some common conversations with our customers whom we work with to ensure they can bring more secure embedded devices to market, and we’re sharing this as we hope that this library will help embedded developers build more secure products. We welcome feedback either via the GitHub issues or via email to our team. We’d love to hear if you use this, how it works for you, and if there are more features which would help your development be more secure.