Chapter 19. SDL Banned Function Calls

In this chapter:

When the C runtime library (CRT) was first created about 25 years ago, the threats to computers were different; machines were not as interconnected as they are today, and attacks were not as prevalent. With this in mind, a subset of the C runtime library must be deprecated for new code and, over time, removed from earlier code. It’s just too easy to get code wrong that uses these outdated functions. Even some of the classic replacement functions are prone to error, too.

Following is a partial list of Microsoft security bulletins that could have been prevented if the banned application programming interfaces (APIs) that led to the security bug had been removed from the code:

Microsoft Bulletin Number

Product and Code

Function

MS02-039

Microsoft SQL Server 2000

sprintf

MS05-010

License Server

lstrcpy

MS04-011

Microsoft Windows (DCPromo)

wvsprintf

MS04-011

Windows (MSGina)

lstrcpy

MS04-031

Windows (NetDDE)

wcscat

MS03-045

Windows (USER)

wcscpy

You can get more info on these security bulletins at http://www.microsoft.com/technet/security/current.aspx. Note that many other software vendors and projects have had similar vulnerabilities.

The Banned APIs

This list is the SDL view of what comprises banned APIs; it is derived from experience with real-world security bugs and focuses almost exclusively on functions that can lead to buffer overruns (Howard, LeBlanc, and Viega 2005). Any function in this section’s tables must be replaced with a more secure version. Obviously, you cannot replace a banned API with another banned API. For example, replacing strcpy with strncpy is not valid because strncpy is banned, too.

Also note that some of the function names might be a little different, depending on whether the function takes ASCII, Unicode, _T (ASCII or Unicode) or multibyte chars. Some function names might include A or W at the end of the name. For example, the StrSafe StringCbCatEx function is also available as StringCbCatExW (Unicode) and StringCbCatExA (ASCII).

Banned String Copy Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

strcpy, wcscpy, _tcscpy, _mbscpy, StrCpy, StrCpyA, StrCpyW, lstrcpy, lstrcpyA, lstrcpyW, strcpyA, strcpyW, _tccpy, _mbccpy

String*[*]Copy or String*CopyEx

strcpy_s

[*] For StrSafe, * should be replaced with Cch (character count) or Cb (byte count).

Banned String Concatenation Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

strcat, wcscat, _tcscat, _mbscat, StrCat, StrCatA, StrCatW, lstrcat, lstrcatA, lstrcatW, StrCatBuffW, StrCatBuff, StrCatBuffA, StrCatChainW, strcatA, strcatW, _tccat, _mbccat

String*Cat or String*CatEx

strcat_s

Banned sprintf Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

wnsprintf, wnsprintfA, wnsprintfW, sprintfW, sprintfA, wsprintf, wsprintfW, wsprintfA, sprintf, swprintf, _stprintf

String*Printf or String*PrintfEx

sprintf_s

Banned “n” sprintf Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

_snwprintf, _snprintf, _sntprintf, nsprintf

String*Printf or String*PrintfEx

_snprintf_s or _snwprintf_s

Banned Variable Argument sprintf Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

wvsprintf, wvsprintfA, wvsprintfW, vsprintf, _vstprintf, vswprintf

String*VPrintf or String*VPrintfEx

_vstprintf_s

Banned Variable Argument “n” sprintf Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

_vsnprintf, _vsnwprintf, _vsntprintf, wvnsprintf, wvnsprintfA, wvnsprintfW,

String*VPrintf or String*VPrintfEx

vsntprintf_s

Banned “n” String Copy Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

strncpy, wcsncpy, _tcsncpy, _mbsncpy, _mbsnbcpy, StrCpyN, StrCpyNA, StrCpyNW, StrNCpy, strcpynA, StrNCpyA, StrNCpyW, lstrcpyn, lstrcpynA, lstrcpynW, _fstrncpy

String*CopyN or String*CopyNEx

strncpy_s

Banned “n” String Concatenation Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

strncat, wcsncat, _tcsncat, _mbsncat, _mbsnbcat, StrCatN, StrCatNA, StrCatNW, StrNCat, StrNCatA, StrNCatW, lstrncat, lstrcatnA, lstrcatnW, lstrcatn, _fstrncat

String*CatN or String*CatNEx

strncat_s

It is common wisdom to replace functions like strcpy with the counted “n” version, such as strncpy. However, in our experience, the “n” functions are also hard to secure (Howard 2004), so we have banned their use in new code.

Banned String Tokenizing Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

strtok, _tcstok, wcstok, _mbstok

None

strtok_s

Banned Makepath Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

makepath, _tmakepath, _makepath, _wmakepath

None

_makepath_s

Banned Splitpath Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

_splitpath, _tsplitpath, _wsplitpath

None

_splitpath_s

Banned scanf Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

scanf, wscanf, _tscanf, sscanf, swscanf, _stscanf

None

sscanf_s

Banned “n” scanf Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

snscanf, snwscanf, _sntscanf

None

_snscanf_s

Banned Numeric Conversion Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

_itoa, _itow, _i64toa, _i64tow, _ui64toa, _ui64tot, _ui64tow, _ultoa, _ultot, _ultow

None

_itoa_s, _itow_s

Banned gets Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

gets, _getts, _gettws

String*Gets

gets_s

Banned IsBad* Functions and Replacements

Banned APIs

 

IsBadWritePtr, IsBadHugeWritePtr, IsBadReadPtr, IsBadHugeReadPtr, IsBadCodePtr, IsBadStringPtr

These functions can mask errors, and there are no replacement functions. You should rewrite the code to avoid using these APIs. If you need to avoid a crash, wrap your usage of the pointer with __try/__except. Doing this can easily hide bugs; you should do this only in areas where it is absolutely critical to avoid a crash (such as crash recovery code) and where you have a reasonable explanation for why the data you’re looking at might be invalid. You should also not catch all exceptions, but only types that you know about. Catching all exceptions is just as bad as using IsBad*Ptr.

For IsBadWritePtr, filling the destination buffer using memset is a preferred way to validate that output buffers are valid and large enough to hold the amount of space that the caller claims they provided.

Banned OEM Conversion Functions and Replacements

Banned APIs

Windows Replacement

CharToOem, CharToOemA, CharToOemW, OemToChar, OemToCharA, OemToCharW, CharToOemBuffA, CharToOemBuffW

WideCharToMultiByte

Banned Stack Dynamic Memory Allocation Functions and Replacements

Banned APIs

Windows Replacement

alloca, _alloca

SafeAllocA

For critical functions, such as those accepting anonymous Internet connections, strlen must also be replaced:

Banned String Length Functions and Replacements

Banned APIs

StrSafe Replacement

Safe CRT Replacement

strlen, wcslen, _mbslen, _mbstrlen, StrLen, lstrlen

String*Length

strlen_s

Why the “n” Functions Are Banned

The classic C runtime “n” functions (such as strncpy and strncat) are banned because they are so hard to call correctly. The authors have seen numerous errors calling these functions in an attempt to make code more secure. Note that we’re not saying the replacements are perfect, but issues with the current “n” functions include non-null termination of overflowed buffers and no error returns on overflow.

The newer StrSafe and Safe CRT functions are more consistent on failure.

Important Caveat

Simply replacing a banned function call with a better replacement does not guarantee that the code is secure. It’s possible to misuse the replacement function, most commonly by getting the destination buffer size wrong.

Best Practices

Best Practices

Review all instances of replaced function calls, and verify that the destination buffer size is correct.

Choosing StrSafe vs. Safe CRT

There is an overlap between these two sets of replacement C runtime functions. Which you choose depends on your specific situation; the following table should help you make the decision. In some cases, you might have little choice but to use one over the other; for example, if your code calls itoa a great deal, there is no replacement in StrSafe, but there is in Safe CRT. You would need to either code around the itoa call or use Safe CRT.

 

StrSafe

Safe CRT

Distribution Method

Web (msdn.microsoft.com)

Microsoft Visual Studio 2005

# Headers

One (StrSafe.h)

Numerous (various C runtime headers)

Library Version Available

Yes

Yes

Inline Version Available

Yes

No

Industry Standard

No

Not Yet (Secure C Lib Functions)

Kernel Mode

Yes

No

Return Type

HRESULT (user mode) or NTSTATUS (kernel mode)

Varies by function (errno_t)

Requires Code Changes

Yes

Yes

Main Focus

Buffer overrun issues

Various, including buffer overruns

Using StrSafe

To use StrSafe in your C or C++ code, simply add the following header:

#include "strsafe.h"

This will make the functions inline. If you want to use the library version, strsafe.lib, add the following to your code:

#define STRSAFE_LIB
#include "strsafe.h"

Note that all the StrSafe functions include Rtl versions for kernel use.

StrSafe Example

The following code

void Function(char *s1, char *s2) {
    char temp[32];
    strcpy(temp,s1);
    strcat(temp,s2);
}

when converted to StrSafe might look like this:

HRESULT Function(char *s1, char *s2) {
    char temp[32];
    HRESULT hr = StringCchCopy(temp,_countof(temp),s1);
    if (FAILED(hr)) return hr;
    return StringCchCat(temp,_countof(temp),s2);
}

Using Safe CRT

The Safe CRT is included with Visual Studio 2005. When you compile code using this compiler, it will automatically warn you of the deprecated functions in the code. Also, in some cases, the compiler will change some function calls to safe function calls if the destination buffer size is known at compile time and CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES is #defined in the code.

For example, the following code

int main(int argc, char* argv[]) {
    char t[10];
       ...
    if (2==argc)
        strcpy(t,argv[1]);

       ...
    return 0;

}

is changed by the compiler to this:

int main(int argc, char* argv[]) {
    char t[10];
   ...   if (2==argc)
       strcpy_s(t,_countof(t),argv[1]);

   ...
   return 0;
}

Safe CRT Example

The following code

void Function(char *s1, char *s2) {
    char temp[32];
    strcpy(temp,s1);
    strcat(temp,s2);
}

when converted to the Safe CRT might look like this:

errno_t Function(char *s1, char *s2) {
    char temp[32];
    errno_t err = strcpy_s(temp,_countof(temp),s1);
    if (!err) return err;
    return strcat_s(temp,_countof(temp),s2);
}

Other Replacements

If you are using C++, you should seriously consider using the std::string template class rather than manipulating buffers directly.

Many *nix variants, including OpenBSD and some Linux operating systems, include support for string copy replacements strlcpy and strlcat (Miller and de Raadt 1999).

Tools Support

The Visual Studio 2005 compiler has built-in deprecations for these functions; all C4996 compiler warnings should be investigated to make sure that the function in question is not on the preceding banned list. Also, look out for code that disables this warning, such as #pragma warning(disable:4996).

On the CD

On the CD

The companion disc accompanying this book includes a header file named banned.h listing all the banned APIs. If you add this as the first header file in your application, it will detect all banned API instances. It works and has been tested with Microsoft Visual C++ 2003 and 2005 compilers and GNU GCC 3.3.x.

ROI and Cost Impact

Removing banned APIs is one way to reduce potential security bugs with very little engineering effort. As you can see at the start of this document, some Microsoft security bulletins would not have been necessary if banned APIs had not been used.

Metrics and Goals

The metric to track is the number of banned APIs in former code and in new code. The quantity should be zero for new code and should follow a glide path down over time for earlier code.

Important

Important

This list of banned APIs is not static—over time, new functions will be added as new vulnerabilities are discovered and replacement APIs created.

References

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset