A major progress in application security: prove that C Runtime and Windows API impact on security
Michael Howard Security Project Manager Secure Windows Initiative Group Windows XP Group Microsoft Corporation 2001 Abstract: This article discusses common errors when using C and C for function calls and its security hazards, and summarize the correct usage of certain functions. As a continuous effort, in the next few months, we will continue to discuss and provide safety information for more APIs. Brief Introduction Code Check C and C code to find a security weak link, I found some common problems when calling some functions. Although some function calls may have nothing to do with security, it will still be unpatientable security hazards if not used. This article will discuss these errors and their security hazards, and will outline the correct use of some functions. We have already launched a discussion for some security evaluations recorded in MSDN and Platform SDK, we have already launched a discussion (this discussion is still continuing). In the first round of discussion, we outline the top-level function calls that lead to the weak links of Microsoft and non-Microsoft products. We first discuss the following functions that are particularly worth noting that in terms of security: CopyMemoryCreateProcess, CreateProcessAsUser, CreateProcessWithLogonWSetSecurityDescriptorDacl simulation function memcpysprintf, swprintfstrcat, wcscat, _mbscatstrcpy, wcscpy, _mbscpystrncat, wcsncat, _mbsncatWinExecCopyMemory safety evaluation of the first argument must be sufficient to accommodate the count Destination The Source combination size of the byte, otherwise the buffer overflow can occur. In this way, when a violation access occurs, the application may be rejected service attack, or even worse, may cause an attacker to inject the executable code into your process. This is especially true if Destination is a stack-based buffer. It should be noted that the last parameter length is the number of bytes to copy to the Destination, not the size of the Destination. The following code example demonstrates the method of safe use CopyMemory (): void test (char * pbdata) {
Char buf [buffer_size];
CopyMemory (buf, pbdata, min (cbdata, buffer_size);
}
CreateProcess, CreateProcessasuser, CreateProcessWithlogonw Security Evaluation The first parameter lpapplicationName can be NULL. In this case, the name of the executable program must be the first string separated by spaces in LPCommandline. However, if there is a space in the name of the program or the path name, there is a certain risk, because if the space is handled properly, malicious executable may be run. The following example is dangerous because the process will try to run "program.exe" (if the program exists), not "foo.exe". CreateProcess (NULL, "C: / Program files / foo", ...)
If the malicious user wants to create a Troy program named "Program.exe" in the system, any programs that use the "Program Files" directory incorrectly call the CreateProcess will start the Troy program, not the application to call. Be careful not to pass NULL for lPApplicationName to avoid functions to analyze and determine the executable path name based on its runtime parameters. Otherwise, if lpapplicationName is NULL, use quotation marks to cause the executable path in LPCommandline, as shown in the following example. CreateProcess (NULL, "/" C: / Program Files / Foo.exe / "-l -s", ...) SetSecurityDescriptORDACL security rating is not to create a security descriptor with NULL DACL (ie: PDACL is null) Because such DACL cannot provide security for objects. In fact, an attacker can set an EVERYONE (Deny All Access) ACE on the object to reject each person (including administrator) to access the object. NULL DACL did not provide any protective protection for an object. Analog Function Security Evaluation If the call to the analog function fails, the client will not simulate the client, and the client request will be done in the security environment where the process is called. If the process runs as a high privileged account (such as localsystem), or as a member of the management group, the user may be able to perform the operations not allowed in other cases. So, you must always check the returned value called, if this value is not reported, do not continue to perform the client request. The following are some examples: RpcImpersonateClient ImpersonateNamedPipeClient SetThreatToken ImpersonateSelf CoImpersonateClient ImpersonateDdeClientWindow ImpersonateSecurityContext ImpersonateLoggedOnUser memcpy Safety Evaluation dest parameter must be sufficient to accommodate the combined size of the src byte count, otherwise a buffer overflow may occur. In this way, when a violation access occurs, the application may be rejected service attack, or even worse, may cause an attacker to inject the executable code into your process. This is especially true if DEST is based on a stack-based buffer. It should be noted that the last parameter count is the number of bytes to be copied to the DEST, not the size of the DEST. The following code example demonstrates the method of safe use Memcpy (): void test (char * pbdata) {
Char buf [buffer_size];
Memcpy (buf, pbdata, min (cbdata, buffer_size);
}
Sprintf, SWPRINTF Security Evaluation The first parameter buffer must accommodate Format's formatted version and NULL ('/ 0') characters at the end, otherwise the buffer overflow may occur. In this way, when a violation access occurs, the application may be rejected service attack, or even worse, may cause an attacker to inject the executable code into your process. This is especially true if buffer is based on a stack-based buffer. In addition, you should pay attention to the risk of format as a variable. The next example is dangerous, because the attacker may set the szTemplate to "% 90S% 10S", which creates a 100-byte string: void test (char * sztemplate, char * szdata1, char * szdata2) {char BUF [buffer_size];
Sprintf (buf, sztemplate, szdata1, szdata2);
}
Use _snprintf (English) or _SnWprintf should be considered. STRCAT, WCSCAT, _MBSCAT Security Evaluation The first parameter STRDESTINATION must accommodate the current strDestination and strsource combinations and one end '/ 0', otherwise the buffer overflow may occur. In this way, when a violation access occurs, the application may be rejected service attack, or even worse, may cause an attacker to inject the executable code into your process. This is especially true if strDestination is a stack-based buffer. Strncat (English), WCSNCAT or _MBSNCAT should be considered. STRCPY, WCSCPY, _MBSCPY Security Evaluation The first parameter STRDESTINATION must accommodate strsource and end '/ 0', otherwise the buffer overflow may occur. In this way, when a violation access occurs, the application may be rejected service attack, or even worse, may cause an attacker to inject the executable code into your process. This is especially true if strDestination is a stack-based buffer. Strncpy, WCSNCPY or _MBSNCPY should be considered. Strncat, WCSNCAT, _MBSNCAT Security Evaluation The first parameter STRDESTINATION must accommodate the current strDestination and strsource combinations and a last NULL ('/ 0'), otherwise the buffer overflow may occur. In this way, when a violation access occurs, the application may be rejected service attack, or even worse, may cause an attacker to inject the executable code into your process. This is especially true if strDestination is a stack-based buffer. It should be noted that the last parameter count is the number of bytes to copy to the strDestination, not the StrDestination size. Also note that if there is a remaining space in the buffer strDestination, Strncat only adds the end NULL. The following code example demonstrates the safe use of Strncat: void test (char * szwords1, char * szwords2) {
Char buf [buffer_size];
STRNCPY (BUF, Szwords1, Sizeof BUF - 1);
BUF [Buffer_Size - 1] = '/ 0';
Unsigned int cremaining = (Sizeof BUF - Strlen (BUF)) - 1; Strncat (buf, szwords2, cremaining);
}
Winexec security Evaluation executable is considered to be a string separated by spaces in LPCMDline. However, if there is a space in the name of the program or the path name, there is a certain risk, because if the space is handled properly, malicious executable may be run. The following example is dangerous because the process will try to run "program.exe" (if the program exists), not "foo.exe". Winexec ("C: / Program Files / Foo", ...) If the malicious user wants to create a Troj program named "Program.exe" in the system, any program that uses the "Program Files" directory to invade Winexec The Troy program will be started instead of the application to call. In terms of security, we strongly recommend that you use createProcess instead of Winexec. However, if you must use Winexec due to legacy issues, it is necessary to cause the application name to quotation marks, as shown in the following example: Winexec ("/" c: / program files / foo.exe / "-l -s" , ...)
Summary With further understanding of the function error in the future, we will add more content to this function list. If you have any comments on these function calls, welcome to send emails and discuss with me: mikehow@microsoft.com.