界: Input Validation and Representation
输入验证与表示问题是由元字符、交替编码和数字表示引起的。安全问题源于信任输入。这些问题包括:“Buffer Overflows”、“Cross-Site Scripting”攻击、“SQL Injection”等其他问题。
Buffer Overflow
Abstract
在一块分配的内存边界之外写入数据可能会破坏数据、造成程序崩溃或导致恶意代码的执行。
Explanation
Buffer overflow 可能是人们最熟悉的一种软件安全漏洞。虽然绝大多数软件开发者都知道什么是 Buffer overflow 漏洞,但是无论是对继承下来的或是新开发的应用程序来说,Buffer overflow 攻击仍然是一种最常见的攻击形式。对于这个问题出现的原因,一方面是造成 buffer overflow 漏洞的方式有很多种,另一方面是用于防止 buffer overflow 的技术也容易出错。
在一个典型的 buffer overflow 攻击中,攻击者将数据传送到某个程序,程序会将这些数据储存到一个较小的堆栈缓冲区内。结果,调用堆栈上的信息会被覆盖,其中包括函数的返回指针。数据会被用来设置返回指针的值,这样,当该函数返回时,函数的控制权便会转移给包含在攻击者数据中的恶意代码。
虽然这种类型的堆栈 buffer overflow 在某些平台和开发组织中十分常见,但仍不乏存在其他各种类型的 buffer overflow,其中包括堆 buffer overflow 和 off-by-one 错误等。有关 buffer overflow 如何进行攻击的详细信息,许多优秀的著作都进行了相关介绍,如 Building Secure Software [1]、Writing Secure Code [2] 以及 The Shellcoder's Handbook [3]。
在代码层上,buffer overflow 漏洞通常会违反程序员的各种假设。C 和 C++ 中的很多内存处理函数都没有执行边界检查,因而可以轻易地覆盖缓冲区所操作的、已分配的边界。即使是边界函数(如
Buffer overflow 漏洞通常出现在以下代码中:
— 依靠外部的数据来控制行为的代码。
— 受数据属性影响的代码,该数据在代码的临接范围之外执行。
— 代码过于复杂,以致于程序员无法准确预测它的行为。
以下例子分别演示了上面三种情况。
例 1.a:以下示例代码显示了简单的 buffer overflow,它通常由第一种情况所导致,即依靠外部数据来控制行为的代码。该代码使用
注:该类型的 buffer overflow 漏洞(程序可读取数据,然后对剩余数据随后进行的内存操作中的一个数值给予信任)已在图像、音频和其他的文件处理库中频繁地出现。
例 3:这是一个关于第二种情况的例子,代码受未在本地校验的数据属性的影响。在本例中,名为
该代码似乎可以安全地执行边界检查,因为它检测变量长度的大小,该变量长度会在之后用来控制
虽然本例中的代码不是我们所遇见的代码中最复杂的,但是它足以说明为什么要尽可能地降低执行内存操作代码的复杂度。
在一个典型的 buffer overflow 攻击中,攻击者将数据传送到某个程序,程序会将这些数据储存到一个较小的堆栈缓冲区内。结果,调用堆栈上的信息会被覆盖,其中包括函数的返回指针。数据会被用来设置返回指针的值,这样,当该函数返回时,函数的控制权便会转移给包含在攻击者数据中的恶意代码。
虽然这种类型的堆栈 buffer overflow 在某些平台和开发组织中十分常见,但仍不乏存在其他各种类型的 buffer overflow,其中包括堆 buffer overflow 和 off-by-one 错误等。有关 buffer overflow 如何进行攻击的详细信息,许多优秀的著作都进行了相关介绍,如 Building Secure Software [1]、Writing Secure Code [2] 以及 The Shellcoder's Handbook [3]。
在代码层上,buffer overflow 漏洞通常会违反程序员的各种假设。C 和 C++ 中的很多内存处理函数都没有执行边界检查,因而可以轻易地覆盖缓冲区所操作的、已分配的边界。即使是边界函数(如
strncpy()
),使用方式不正确也会引发漏洞。对内存的处理加之有关数据段大小和结构方面所存在种种错误假设,是导致大多数 buffer overflow 漏洞产生的根源。Buffer overflow 漏洞通常出现在以下代码中:
— 依靠外部的数据来控制行为的代码。
— 受数据属性影响的代码,该数据在代码的临接范围之外执行。
— 代码过于复杂,以致于程序员无法准确预测它的行为。
以下例子分别演示了上面三种情况。
例 1.a:以下示例代码显示了简单的 buffer overflow,它通常由第一种情况所导致,即依靠外部数据来控制行为的代码。该代码使用
gets()
函数将一个任意大小的数据读取到堆栈缓冲区中。因为没有什么方法可以限制该函数读取数据的量,所以代码的安全性就依赖于用户始终输入比 BUFSIZE
少的字符数量。例 1.b:这一例子表明模仿 C++ 中
...
char buf[BUFSIZE];
gets(buf);
...
gets()
函数的不安全行为是如此的简单,只要通过使用 >>
运算符将输入读取到 char[]
字符串中。例 2:虽然本例中的代码也是依赖于用户输入来控制代码行为,但是它通过使用边界内存复制函数
...
char buf[BUFSIZE];
cin >> (buf);
...
memcpy()
增加了一个间接级。该函数接受一个目标缓冲区、一个起始缓冲区和要复制的字节数。虽然输入缓冲区由 read()
的边界调用填充,但是 memcpy()
复制的字节数需要由用户指定。
...
char buf[64], in[MAX_SIZE];
printf("Enter buffer contents:\n");
read(0, in, MAX_SIZE-1);
printf("Bytes to copy:\n");
scanf("%d", &bytes);
memcpy(buf, in, bytes);
...
注:该类型的 buffer overflow 漏洞(程序可读取数据,然后对剩余数据随后进行的内存操作中的一个数值给予信任)已在图像、音频和其他的文件处理库中频繁地出现。
例 3:这是一个关于第二种情况的例子,代码受未在本地校验的数据属性的影响。在本例中,名为
lccopy()
的函数将一个字符串作为其变量,然后返回一个堆分配字符串副本,并将该字符串的所有大写字母转化成了小写字母。因为该函数认为 str
总是比 BUFSIZE
小,所以它不会对输入执行任何边界检查。如果攻击者避开对调用 lccopy()
代码的检查,或者如果更改代码,使得程序员对 str
长度的原有假设与实际不符,那么 lccopy()
就会通过无边界调用 strcpy()
溢出 buf
。示例 4:以下代码演示了第三种情况,代码非常复杂,无法轻松预测其行为。该代码来自通用的 libPNG 图像解码器,众多应用程序使用的都是该解码器。
char *lccopy(const char *str) {
char buf[BUFSIZE];
char *p;
strcpy(buf, str);
for (p = buf; *p; p++) {
if (isupper(*p)) {
*p = tolower(*p);
}
}
return strdup(buf);
}
该代码似乎可以安全地执行边界检查,因为它检测变量长度的大小,该变量长度会在之后用来控制
png_crc_read()
复制的数据量。然而,在测试长度前,该代码会立即对 png_ptr->mode
执行检查,如果检查失败,便会发出一个警告,然后会继续进行处理。因为 length
测试在 else if
块中进行,如果针对该代码的首次测试失败,那么就不会再测试 length
,而将其盲目地用于调用 png_crc_read()
,因此很容易引起堆栈 Buffer Overflow。虽然本例中的代码不是我们所遇见的代码中最复杂的,但是它足以说明为什么要尽可能地降低执行内存操作代码的复杂度。
例 5:本例同样演示了第三种情况,程序过于复杂,使其暴露出 buffer overflow 的问题。在这种情况下,问题出现的原因在于其中某个函数的接口不明确,而不是代码结构(同上一个例子中描述的情况一样)。
if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > (png_uint_32)png_ptr->num_palette) {
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
return;
}
...
png_crc_read(png_ptr, readbuf, (png_size_t)length);
getUserInfo()
函数采用一个定义为多字节字符串的用户名和一个指向用户信息结构的指针,这一结构由该用户的相关信息填充。因为 Windows authentication 中的用户名使用 Unicode,所以 username
参数首先要从多字节字符串转换成 Unicode 字符串。然后,这个函数便会错误地将 unicodeUser
的长度以字节形式而不是字符形式传递出去。调用 MultiByteToWideChar()
可能会把 (UNLEN+1)*sizeof(WCHAR)
宽字符或者(UNLEN+1)*sizeof(WCHAR)*sizeof(WCHAR)
字节,写到 unicodeUser
数组,该数组仅分配了 (UNLEN+1)*sizeof(WCHAR)
个字节。如果 username
字符串包含了多于 UNLEN
的字符,那么调用 MultiByteToWideChar()
将会溢出 unicodeUser
缓冲区。
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);
}
References
[1] J. Viega, G. McGraw Building Secure Software Addison-Wesley
[2] M. Howard, D. LeBlanc Writing Secure Code, Second Edition Microsoft Press
[3] J. Koziol et al. The Shellcoder's Handbook: Discovering and Exploiting Security Holes John Wiley & Sons
[4] About Strsafe.h Microsoft
[5] Standards Mapping - Common Weakness Enumeration CWE ID 120, CWE ID 129, CWE ID 131, CWE ID 787
[6] Standards Mapping - Common Weakness Enumeration Top 25 2019 [1] CWE ID 119, [3] CWE ID 020, [12] CWE ID 787
[7] Standards Mapping - Common Weakness Enumeration Top 25 2020 [5] CWE ID 119, [3] CWE ID 020, [2] CWE ID 787
[8] Standards Mapping - Common Weakness Enumeration Top 25 2021 [1] CWE ID 787, [4] CWE ID 020, [17] CWE ID 119
[9] Standards Mapping - Common Weakness Enumeration Top 25 2022 [1] CWE ID 787, [4] CWE ID 020, [19] CWE ID 119
[10] Standards Mapping - Common Weakness Enumeration Top 25 2023 [1] CWE ID 787, [6] CWE ID 020, [17] CWE ID 119
[11] Standards Mapping - DISA Control Correlation Identifier Version 2 CCI-002754, CCI-002824
[12] Standards Mapping - General Data Protection Regulation (GDPR) Indirect Access to Sensitive Data
[13] Standards Mapping - Motor Industry Software Reliability Association (MISRA) C Guidelines 2012 Rule 1.3
[14] Standards Mapping - Motor Industry Software Reliability Association (MISRA) C Guidelines 2023 Directive 4.14, Rule 1.3, Rule 21.17
[15] Standards Mapping - Motor Industry Software Reliability Association (MISRA) C++ Guidelines 2008 Rule 0-3-1, Rule 18-0-5
[16] Standards Mapping - NIST Special Publication 800-53 Revision 4 SI-10 Information Input Validation (P1), SI-16 Memory Protection (P1)
[17] Standards Mapping - NIST Special Publication 800-53 Revision 5 SI-10 Information Input Validation, SI-16 Memory Protection
[18] Standards Mapping - OWASP Application Security Verification Standard 4.0 5.1.3 Input Validation Requirements (L1 L2 L3), 5.1.4 Input Validation Requirements (L1 L2 L3), 5.4.1 Memory/String/Unmanaged Code Requirements (L1 L2 L3), 5.4.2 Memory/String/Unmanaged Code Requirements (L1 L2 L3), 14.1.2 Build (L2 L3)
[19] Standards Mapping - OWASP Mobile 2014 M7 Client Side Injection
[20] Standards Mapping - OWASP Mobile 2024 M4 Insufficient Input/Output Validation
[21] Standards Mapping - OWASP Mobile Application Security Verification Standard 2.0 MASVS-CODE-4
[22] Standards Mapping - OWASP Top 10 2004 A5 Buffer Overflow
[23] Standards Mapping - OWASP Top 10 2013 A1 Injection
[24] Standards Mapping - OWASP Top 10 2017 A1 Injection
[25] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1 Requirement 6.5.5
[26] Standards Mapping - Payment Card Industry Data Security Standard Version 1.2 Requirement 6.3.1.1
[27] Standards Mapping - Payment Card Industry Data Security Standard Version 2.0 Requirement 6.5.2
[28] Standards Mapping - Payment Card Industry Data Security Standard Version 3.0 Requirement 6.5.2
[29] Standards Mapping - Payment Card Industry Data Security Standard Version 3.1 Requirement 6.5.2
[30] Standards Mapping - Payment Card Industry Data Security Standard Version 3.2 Requirement 6.5.2
[31] Standards Mapping - Payment Card Industry Data Security Standard Version 3.2.1 Requirement 6.5.2
[32] Standards Mapping - Payment Card Industry Data Security Standard Version 4.0 Requirement 6.2.4
[33] Standards Mapping - Payment Card Industry Software Security Framework 1.0 Control Objective 4.2 - Critical Asset Protection
[34] Standards Mapping - Payment Card Industry Software Security Framework 1.1 Control Objective 4.2 - Critical Asset Protection, Control Objective B.3.1 - Terminal Software Attack Mitigation, Control Objective B.3.1.1 - Terminal Software Attack Mitigation, Control Objective B.3.1.2 - Terminal Software Attack Mitigation
[35] Standards Mapping - Payment Card Industry Software Security Framework 1.2 Control Objective 4.2 - Critical Asset Protection, Control Objective B.3.1 - Terminal Software Attack Mitigation, Control Objective B.3.1.1 - Terminal Software Attack Mitigation, Control Objective B.3.1.2 - Terminal Software Attack Mitigation, Control Objective C.3.2 - Web Software Attack Mitigation
[36] Standards Mapping - SANS Top 25 2009 Risky Resource Management - CWE ID 119
[37] Standards Mapping - SANS Top 25 2010 Risky Resource Management - CWE ID 120, Risky Resource Management - CWE ID 129, Risky Resource Management - CWE ID 131
[38] Standards Mapping - SANS Top 25 2011 Risky Resource Management - CWE ID 120, Risky Resource Management - CWE ID 131
[39] Standards Mapping - Security Technical Implementation Guide Version 3.1 APP3510 CAT I, APP3590.1 CAT I
[40] Standards Mapping - Security Technical Implementation Guide Version 3.4 APP3510 CAT I, APP3590.1 CAT I
[41] Standards Mapping - Security Technical Implementation Guide Version 3.5 APP3510 CAT I, APP3590.1 CAT I
[42] Standards Mapping - Security Technical Implementation Guide Version 3.6 APP3510 CAT I, APP3590.1 CAT I
[43] Standards Mapping - Security Technical Implementation Guide Version 3.7 APP3510 CAT I, APP3590.1 CAT I
[44] Standards Mapping - Security Technical Implementation Guide Version 3.9 APP3510 CAT I, APP3590.1 CAT I
[45] Standards Mapping - Security Technical Implementation Guide Version 3.10 APP3510 CAT I, APP3590.1 CAT I
[46] Standards Mapping - Security Technical Implementation Guide Version 4.2 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[47] Standards Mapping - Security Technical Implementation Guide Version 4.3 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[48] Standards Mapping - Security Technical Implementation Guide Version 4.4 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[49] Standards Mapping - Security Technical Implementation Guide Version 4.5 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[50] Standards Mapping - Security Technical Implementation Guide Version 4.6 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[51] Standards Mapping - Security Technical Implementation Guide Version 4.7 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[52] Standards Mapping - Security Technical Implementation Guide Version 4.8 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[53] Standards Mapping - Security Technical Implementation Guide Version 4.9 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[54] Standards Mapping - Security Technical Implementation Guide Version 4.10 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[55] Standards Mapping - Security Technical Implementation Guide Version 4.11 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[56] Standards Mapping - Security Technical Implementation Guide Version 4.1 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[57] Standards Mapping - Security Technical Implementation Guide Version 5.1 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[58] Standards Mapping - Security Technical Implementation Guide Version 5.2 APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[59] Standards Mapping - Security Technical Implementation Guide Version 5.3 APSC-DV-002530 CAT II, APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[60] Standards Mapping - Security Technical Implementation Guide Version 6.1 APSC-DV-002530 CAT II, APSC-DV-002560 CAT I, APSC-DV-002590 CAT I
[61] Standards Mapping - Web Application Security Consortium Version 2.00 Buffer Overflow (WASC-07)
[62] Standards Mapping - Web Application Security Consortium 24 + 2 Buffer Overflow
desc.dataflow.cpp.buffer_overflow