Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Secure String Handling in Windows Applications

4.82/5 (12 votes)
9 Mar 2014CPOL11 min read 63.7K   975  
This article explains about Strsafe, Secured C run time library (CRT) and safe STL functions.

Introduction

Confidentiality, integrity and availability (CIA) are the core principles of information security. Confidentiality refers to limiting information access and allows only authorized users. Integrity refers to trust worthiness of information. Availability refers to the availability of computer information. Security principle should be considered in the entire software development life cycle. Microsoft gives higher priority for building secured environment for customers and provides Microsoft Security Development Lifecycle (SDL) methodologies for building secured applications. Security should be considered in requirements, analysis, design, implementation, verification and release phases. Many system side applications are developed by using C and C++ programming languages. The C and C++ vulnerabilities allow the attacker to attack the operating system lower level layer. Microsoft increases the security for Microsoft products and gives Microsoft Security Development Lifecycle (SDL) process for developing secured software using Microsoft technologies. The software developers should consider security in the part of development process.

Secure String Handling

C/C++ doesn’t support any build in data type for strings. C/C++ treats string as array of characters. But, C++ can make use of Standard Template Library string class. The security should be considered when the application uses both standard template library (STL) and C style strings. The C style strings are NULL terminated. The Windows C/C++ programmers have many options for string handling. The developers can use C Run time library (CRT) (strcpy, strcmp, etc), Windows string functions (lstrcmp, lstrcpy, etc), C++ STL and MFC/ATL library String functions. Microsoft increased security for all the string functions because most of the application security attack is based on buffer overflow.

Microsoft released Strsafe functions for increased Windows applications security. Later, Microsoft enhanced the CRT libraries for increased security. It helps the developers build secured applications and Microsoft uses those functions internally too. Microsoft rebuilds the ATL and MFC libraries for making use of secured C run time functions. So, if developers rebuild their applications by using new versions of MFC and ATL, they will make sure the applications use secured version libraries.

The Secure string handling comes under Secure Development Lifecycle (SDL) Practice #9: Deprecate Unsafe Functions. Microsoft SDL recommends making use of Banned.H, Strsafe.h (with Visual Studio) and Safe CRT (with Visual Studio). The National Institute of Standards and Technology (NIST) states that designing the secured software during the early stage can cost 30 times less than fixing them post release.

Single Byte Character Set (SBCS), Multi Byte Character Set (MBCS) and Unicode

The developer should be aware of the difference between Single Byte Character set (SBCS), Multi byte Character set (MBCS) and Unicode. The Single Byte Character allocates only a single byte memory for each character. Single byte character set (SBCS) is sufficient to represent the ASCII character and many European languages. But some non-European characters require more than one byte character. So, it requires multi byte character set (MBCS). A Unicode character is a 2-byte multilingual character code. Most of the modern Microsoft operating systems use Unicode format only. Even if you develop ASCII version, the Microsoft layer converts into Unicode format before calling the function. So, it will reduce the performance. So, Microsoft recommends using Unicode Strings.

The memory allocation for Unicode and SBCS/MBCS are different. So, Microsoft provides two versions of functions. The function calls the ASCII or Unicode based on application compiler settings. Microsoft also provides generic text data type for handling both Unicode and SBCS/MBCS. It will call SBCS/MBCS functions for non-Unicode and Unicode functions for Unicode compiler options. Microsoft recommends making use of the Unicode version for future development. So, the component can be easily migrated to different locale without much effort.

The Windows API provides separate functions for ASCII and Unicode. The Strsafe family function provides the separate function A for ASCII or W for Unicode at the end of the name. For example, the StrSafe StringCbCatEx function is available for StringCbCatExW (Unicode) and StringCbCatExA (ASCII). The Windows API MultiByteToWideChar and WideCharToMultiByte are used for translating strings between Unicode and ASCII.

Banned Application Programming Interface (API)

Microsoft C++ compiler gives more options for application's security during compile time itself. Microsoft Visual C++ compiler gives a warning when the source code uses banned string API. The Strsafe.h provides the secure functionality for C style strings. Alternatively, the developers can choose Strsafe or Safe CRT for building secured applications. The list of banned API and alternative functions are discussed in Security Development Lifecycle (SDL) Banned Function Calls. If the strcpy or strcat is used incorrectly, it leads to buffer overflow. So, Microsoft added those kinds of family functions to Banned API list. The banned API listing is applicable for both Microsoft and Non Microsoft technologies and platforms. The N family functions are also listed in Banned API list. The C runtime “n” functions make them difficult to use and is one of the reasons why they are listed as part of the Microsoft SDL Banned API listing.

As per SDL list of Banned Function Calls, the developer should include #include “banned.h”;. This will be able to locate any banned functions in code. The full list of banned APIs is also included in the header file. Alternately, if you are using the compiler in Visual Studio 2005 or later, you have a built-in way to check for these banned functions. To catch banned C runtime functions, you can compile with /W4 and then triage all C4996 warnings.

C++
#include "c:\banned.h"
1>c:\development\c++\ban\ban\test.cpp(79) : 
warning C4995: 'StrCpyN': name was marked as #pragma deprecated
1>c:\development\c++\ban\ban\test.cpp(79) : 
warning C4995: 'StrCpyNW': name was marked as #pragma deprecated  

Strsafe and Secured C Run time Library (CRT)

Microsoft released Strsafe library for developing secured Windows applications. Software security should be considered for the entire software development life cycle (SDLC). The input validation is the major problem for system and web programming. It may have variations like buffer overflow, underflow, etc. The application uses array of characters for many places for string compare, Append a string, Append characters of a string, String Copy, Get String input, String length and format the string characters. The functions supported from Strsafe contain guaranteed null terminated string, return HRESULT for successful call, separate functions for corresponding character count ("cch") or byte count ("cb") version[This articles explains only about cch version].

After Strsafe, Microsoft wants to enhance the security for C run time library. So, CRT provides secure _s function for validating their arguments. It checks the values are valid, buffers have enough memory space, etc. This functions return errno_t for finding the success or failure. The release build auto terminates and debug version will gives the assertion dialog box for debugging further. This article explains about Strsafe, Secured C run time library (CRT) and safe STL functions.

Copy String

The secured string copy supports in wcscpy_s(wide-character), _mbscpy_s(multibyte-character) and strcpy_s formats. The arguments and return value of wcscpy_s are wide character strings and _mbscpy_s are multibyte character strings. Otherwise, these three functions behave identically.

The strcopy functions don’t accept the destination buffer size as an input. So, the developer doesn’t have control for validating the size of destination buffer size. The _countof macro is used for computing the number of elements in a statically-allocated array. It doesn’t work with pointer type. The wcscpy_s takes the destination string, Size of the destination string buffer and null terminated source string.

Copy string using secured CRT

C++
wchar_t safe_copy_str1[]=L"Hello world";
wchar_t safe_copy_str2[MAX_CHAR];

wcscpy_s( safe_copy_str2, _countof(safe_copy_str2),safe_copy_str1 );

printf ("After copy string = %S\n\n", safe_copy_str2);

The StringCchCopy function takes Pointer to a destination buffer, Size of the destination buffer in characters and pointer to a source string. It returns S_OK for successful; STRSAFE_E_INVALID_PARAMETER for destination buffer is 0 or max STRSAFE_MAX_CCH and STRSAFE_E_INSUFFICIENT_BUFFER for the copy failed for insufficient buffer. The StringCchCopy is a generic version equal to TCHAR family functions. It will apply A version for ASCII and w version for wide character function.

The StringCchCopyEx function provides more options. The Ex function includes the parameter for address of a pointer to the end of Destination, Pointer to a variable that indicates the number of unused characters in destination and different flags (STRSAFE_FILL_BEHIND_NULL, STRSAFE_IGNORE_NULLS, STRSAFE_FILL_ON_FAILURE, STRSAFE_NULL_ON_FAILURE and STRSAFE_NO_TRUNCATION).

Copy and append String using Strsafe

C++
wchar_t wsString[128];
HRESULT Res;

Res= StringCchCopy(wsString, _countof(wsString), L"Hello ");

if (Res != S_OK) {
   printf("StringCchCopy Failed: %S\n", wsString);
   exit(-1);
}

Res= StringCchCat(wsString,sizeof(wsString),L" World!");

if (Res != S_OK) {
   printf("StringCchCat Failed: %s\n", wsString);
   exit(-1);
}
printf("%S\n", wsString);

Get String

The gets function doesn’t validate the string size. The secured version gets_s validates the input string size. If the buffer size is small, it will give a Buffer which is too small an error in debug mode [Figure 1]. When I run the application and give more character for the allocated memory produced the following Assertion error dialog during debug build.

Get User input String using CRT

C++
#define MAX_BUF 10

// include
// do

 wchar_t safe_getline[MAX_BUF];

 if (gets_s(safe_getline, MAX_BUF) == NULL) {
      printf("invalid input.\n");
      abort();
 }

 printf("%S\n", safe_getline);

If the buffer is small, then this function invokes an invalid parameter handler. If execution is allowed to continue, these functions return NULL and set errno to EINVAL.

Error window

The StringCchGets takes a pointer to a buffer which receives the copied characters and Size of the destination buffer in characters parameters. It will return S_OK for successful get string. It will return STRSAFE_E_END_OF_FILE, STRSAFE_E_INVALID_PARAMETER and STRSAFE_E_INSUFFICIENT_BUFFER for error condition.

Get User input String using Strsafe

C++
wchar_t wsString[128];
HRESULT Res;

Res=StringCchGets(wsString, sizeof(wsString));

if (Res != S_OK) {
   printf("StringCchGets Failed: %S\n", wsString);
   exit(-1);
}

printf("%S \n",wsString);

String Length

The StringCchLength uses for getting the length for the string in characters which does not including the terminating null character. It also takes the maximum number of characters allowed in wsString and returns the length of the input string. It returns S_OK for successful call and STRSAFE_E_INVALID_PARAMETER for failure call.

Get String lengths using Strsafe

C++
wchar_t wsString[] = L"Hello World";
size_t length;
HRESULT Res;

Res = StringCchLength(wsString, MAX_PATH, &length);

if (Res != S_OK) {
   printf("StringCchLength Failed: %S\n", wsString);
   exit(-1);
}

printf("StringCchLength = %d \n",length);

Format String

The StringCchPrintf accepts the list of arguments and return the string. The StringCchPrintf function takes Pointer to a buffer and size of the destination buffer. It returns S_OK for successful call and STRSAFE_E_INVALID_PARAMETER and STRSAFE_E_INSUFFICIENT_BUFFER failed call. The Uncontrolled Format String gives ‘Command Injection’ attacks.

Format String using Strsafe

C++
TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;

int val1 = 10;
int val2= 20;

HANDLE hStdout;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

if( hStdout == INVALID_HANDLE_VALUE )
    return 1;

StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), val1, val2);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);

WriteConsole(hStdout, msgBuf, cchStringSize, &dwChars, NULL);

Secured Standard Template Library (STL)

The standard C++ library is enhanced for use secured string and character handling. Microsoft enhanced the standard template library for security. STL added new functions with _s for security. The following table contains the unsafe function and safer functions.

STL Secured STL
basic_string::copybasic_string::_Copy_s
basic_streambuf::sgetnbasic_streambuf::_Sgetn_s
basic_streambuf::xsgetnbasic_streambuf::_Xsgetn_s
char_traits::copychar_traits::_Copy_s
char_traits::movechar_traits::_Move_s
ctype::narrowctype::_Narrow_s
ctype::do_narrowctype::_Do_narrow_s
ctype::widenctype::_Widen_s
ctype::do_widenctype::_Do_widen_s

All secured STL functions are validated with the size of the destination string. Secured STL enhanced the debug iterator and checked iterators for making iterators and algorithms more secure. The Microsoft C++ runtime detects the incorrect use of iterator and asserts and displays a dialog box at run time. This will enable only program compiled in debug mode.

Checked iterators do not overwrite the bounds of container. It works for both release and debug build. If the program defines #define _SECURE_SCL 1, all the standard iterators are checked. The _SECURE_SCL default value is 1. If the program defines #define _SECURE_SCL_THROWS 1, an out of range iterator use causes an exception at runtime. The _SECURE_SCL_THROWS default value is 0 (program will be terminated by default).

The following STL functions will generate runtime error if they face outside the bounds:

  • basic_string, valarray and bitset
  • back, front and operator[] operations for dequeue and vector
  • back and front operations for list and queue

Difference between Strsafe and CRT

No StrsafeCRT
1 Run on kernel modeRun on user mode
2 Always NULL-terminate the stringParameter Validation. Includes NULL values passed to the functions, Null termination, enumerated values for validity, integral values are in valid ranges
3 Always return HRESULT return codesZero if successful, otherwise an error code
4 Support 32-bit and 64-bit environments.Support 32-bit and 64-bit environments.
5 Windows software development kit Microsoft Visual Studio
6 Include One headerInclude Many headers
7 Supports from Windows XP with Service Pack 2 onwardsSupports from Visual C++ 2005 onwards
8 All functions require size of destination buffer parameterSized Buffers
9 Buffer overflowsBuffer overflows and other vulnerabilities
10 Only string handlingIncludes String handling and Windows security, File system security, Enhanced error reporting, etc.

Conclusion

Microsoft is concentrating more about secured application development. The buffer overflow and other input validation allow the hacker to attack the applications (DOS or DDOS attacks). There is no single document or guide for write secured applications. The guidelines provided by Microsoft make it difficult for attacking the applications in Microsoft environment. The security should consider all the phases in software development. It doesn’t mean the security is considered only for development phase. This article explains only about secured string handling. But, Microsoft released Security Development Lifecycle (SDL) guidelines version 5.0 (Updated November 5, 2010) for developing secured application development. Microsoft is continuously updating Security Development Lifecycle (SDL) guidelines based on current vulnerabilities.

Summary

  1. Banned API is the set of functions calls that you should avoid for both new applications and legacy application development. This list can vary based on current vulnerabilities.
  2. If the application is built on Windows:
    1. Use Strsafe functions and Validate return values.
    2. Else if the application is built on CRT, use Secured CRT functions.
  3. Rebuild MFC and ATL based applications using latest Microsoft libraries which are built using secured versions.
  4. If application uses STL, check safe functions availability.
  5. Follow Microsoft Secured development life cycle (SDL) 5.0 guidelines.

Points of Interest

  1. Microsoft Security Development Life Cycle
  2. MSDN Visual C++ 2008
  3. MSDN Magazine
  4. Security Development Lifecycle (SDL) Banned Function Calls
  5. banned.h

History

  • 9th March 2014: Updated __countof for StringCchCopy, Thanks to virtualnik
  • 12th May, 2011: Updated 'Strafe' and 'Starsafe' to "Strsafe", thanks to Stefan63
  • 15th April, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)