在多字節和 Unicode 字符之間轉換的函數很容易引起 buffer overflow。
Windows 提供了 MultiByteToWideChar()、WideCharToMultiByte()、UnicodeToBytes() 和 BytesToUnicode() 函數,以在多字節(通常為 ANSI)字符串和 Unicode(寬字符)字符串之間進行轉換。由于這些函數的長度參數所指定的單位各不相同,一個是字節,另一個是字符,使得它們的使用很容易出錯。在一個多字節字符串中,每一個字符占用的字節數是可變的,因此,此類字符串的長度很容易指定為所有字節數的總量。但在 Unicode 中,字符通常有固定的長度,所以字符串長度一般都是根據它們所包含的字符數來決定的。所以,在長度參數中錯誤地指定了錯誤的單位,會導致 buffer overflow。
示例:以下函數采用一個定義為多字節字符串的用戶名和一個指針來組成用戶信息的結構,并以用戶相關信息對該結構進行填充。因為在 Windows authentication 中,用戶名使用 Unicode,所以 username 參數是第一個從多字節字符串轉換成 Unicode 字符串的參數。
void getUserInfo(char *username, struct _USER_INFO_2 info){
WCHAR unicodeUser[UNLEN+1];
MultiByteToWideChar(CP_ACP, 0, username, -1,
unicodeUser, sizeof(unicodeUser));
NetUserGetInfo(NULL, unicodeUser, 2, (LPBYTE *)&info);
}
unicodeUser 的長度以字節形式傳遞出去,而不是字符形式。調用 MultiByteToWideChar() 可能會把 (UNLEN+1)*sizeof(WCHAR) 寬字符或者 (UNLEN+1)*sizeof(WCHAR)*sizeof(WCHAR) 字節,寫到 unicodeUser 數組,該數組僅分配了 (UNLEN+1)*sizeof(WCHAR) 字節。如果 username 字符串包含了多于 UNLEN 的字符,那么調用 MultiByteToWideChar() 將會溢出 unicodeUser 緩沖區。
[1] Standards Mapping - OWASP Top 10 2004 - (OWASP 2004) A5 Buffer Overflow
[2] Standards Mapping - Security Technical Implementation Guide Version 3 - (STIG 3) APP3590.1 CAT I
[3] Standards Mapping - Security Technical Implementation Guide Version 3.4 - (STIG 3.4) APP3590.1 CAT I
[4] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 176, CWE ID 251
[5] Standards Mapping - Payment Card Industry Data Security Standard Version 1.2 - (PCI 1.2) Requirement 6.3.1.1
[6] Standards Mapping - Payment Card Industry Data Security Standard Version 2.0 - (PCI 2.0) Requirement 6.5.2
[7] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1 - (PCI 1.1) Requirement 6.5.5
[8] Security Considerations:International Features Microsoft