赞
踩
CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer(没能将内存操作限制在边界范围内)
ID: 119 类型:类 | 状态:可用 |
描述
软件在内存缓冲区上执行操作,但它可以读取或写入缓冲区预期边界之外的内存位置。
扩展描述
某些语言允许直接寻址内存位置,并且不会自动确保这些位置对正在引用的内存缓冲区有效。这可能导致同其它变量、数据结构或内部程序数据相关联的内存读写操作被执行。
因此,攻击者可能能够执行任意代码、更改预期的控制流、读取敏感信息或导致系统崩溃。
关联视图
与“研究层面”视图(CWE-1000)相关
同“已发布弱点简图”(CWE-1003)视图相关
与“开发层面”视图(CWE-699)相关
同“七种致命错误” (CWE-700)视图相关
引入模式
阶段 | 说明 |
架构与设计 | |
实现 | |
操作 |
应用平台
语言
C (经常出现)
C++ (经常出现)
Class: Assembly (出现的可能性不确定)
后果
范围 | 冲击 | 可能性 |
完整性 | 技术冲击: 执行未获授权的代码或命令; 修改内存 如果攻击者可以有效地控制可访问的内存,则可以执行任意代码,就像标准缓冲区溢出一样。如果攻击者可以覆盖指针的内存值(通常为32或64位),那么他们可以将函数指针重定向到自己的恶意代码。即使攻击者只能修改单字节代码,也可以执行任意代码。有时,这是因为同一个问题可以重复利用,达到同样的效果。另一些时候,这是因为攻击者可以覆盖安全关键的应用程序特定数据,例如指示用户是否是管理员的标志。 | |
可利用性 | 技术冲击: 内存读取; DoS: 崩溃、推出或者重启: DoS: 资源消耗(CPU): DoS: 资源消耗 (内存): 越界的内存访问很可能导致相关内存的损坏,或者指令的损坏,可能导致崩溃。其他导致可用性不足的攻击是可能的,包括将程序放入无限循环。 | |
保密性 | 技术冲击: 内存读取 在越界读取的情况下,攻击者可以访问敏感信息。如果敏感信息包含系统细节,例如内存中的当前缓冲区位置,则可以使用这些知识来策划进一步的攻击,可能会产生更严重的后果。 |
被利用的可能性:
高
示例
例1
此示例从用户获取IP地址,验证其格式是否正确,然后查找主机名并将其复制到缓冲区中。
(问题代码)
Example Language: C
void host_lookup(char *user_supplied_addr){
struct hostent *hp;
in_addr_t *addr;
char hostname[64];
in_addr_t inet_addr(const char *cp);
/*routine that ensures user_supplied_addr is in the right format for conversion */
validate_addr_form(user_supplied_addr);
addr = inet_addr(user_supplied_addr);
hp = gethostbyaddr( addr, sizeof(struct in_addr), AF_INET);
strcpy(hostname, hp->h_name);
}
此函数分配一个64字节的缓冲区来存储主机名,但是不能保证主机名不会大于64字节。如果攻击者指定的地址解析为非常大的主机名,那么我们可能会覆盖敏感数据,甚至将控制流放弃给攻击者。
请注意,此示例还包含一个未检差的返回值(CWE-252),它可能导致空指针间接引用(CWE-476)。
例2
此示例将编码过程应用于输入字符串,并将其存储到缓冲区中
(问题代码)
Example Language: C
char * copy_input(char *user_supplied_string){
int i, dst_index;
char *dst_buf = (char*)malloc(4*sizeof(char) * MAX_SIZE);
if ( MAX_SIZE <= strlen(user_supplied_string) ){
die("user string too long, die evil hacker!");
}
dst_index = 0;
for ( i = 0; i < strlen(user_supplied_string); i++ ){
if( '&' == user_supplied_string[i] ){
dst_buf[dst_index++] = '&';
dst_buf[dst_index++] = 'a';
dst_buf[dst_index++] = 'm';
dst_buf[dst_index++] = 'p';
dst_buf[dst_index++] = ';';
}
else if ('<' == user_supplied_string[i] ){
/* encode to < */
}
else dst_buf[dst_index++] = user_supplied_string[i];
}
return dst_buf;
}
程序员试图对用户控制的字符串中的符号和字符进行编码,但是在应用编码过程之前,会验证字符串的长度。此外,程序员假定编码扩展只将给定字符扩展4倍,而‘&’字符的编码长度却扩展5倍。因此,当编码过程扩展字符串时,如果攻击者提供一个包含多个‘&’字符的字符串,则可能溢出目标缓冲区。
例3
下面的示例要求用户在数组中输入偏移量以选择项。
(问题代码)
Example Language: C
int main (int argc, char **argv) {
char *items[] = {"boat", "car", "truck", "train"};
int index = GetUntrustedOffset();
printf("You selected %s\n", items[index-1]);
}
程序员允许用户在列表中指定要选择的元素,但是攻击者可以提供越界偏移量,从而导致缓冲区越界读取(CWE-126)。
例4
在下面的代码中,该方法从特定数组索引位置的数组中检索一个值,该值作为该方法的输入参数给定。
(问题代码)
Example Language: C
int getValueFromArray(int *array, int len, int index) {
int value;
// check that the array index is less than the maximum
// length of the array
if (index < len) {
// get the value at the specified index of the array
value = array[index];
}
// if array index is invalid then output error message
// and return value indicating error
else {
printf("Value is: %d\n", array[index]);
value = -1;
}
return value;
}
但是,此方法只验证给定的数组索引是否小于数组的最大长度,但不检查最小值(CWE-839)。这将允许接受负值作为输入数组索引,这将导致缓冲区下界之下读取(CWE-125),并允许访问敏感内存。应检查输入数组索引,以验证是否在数组所需的最大和最小范围内(CWE-129)。在这个例子中,if语句应该修改为包含一个最小范围检查,如下所示。
(正确代码)
Example Language: C
...
// check that the array index is within the correct
// range of values for the array
if (index >= 0 && index < len) {
...
例5
Windows提供了对多字节字符串执行各种操作的MBS函数系列。当向这些函数传递格式不正确的多字节字符串(例如包含有效前导字节的字符串,后跟一个空字节)时,它们可以读或写超过字符串缓冲区的结尾,从而导致缓冲区溢出。以下所有功能都会造成缓冲区溢出的风险:_mbsinc_mbsdec_mbsncat_mbsncpy_mbsnextc_mbsnset_mbsrev_mbsset_mbsstr_mbstok_mbccpy_mbslen
应对措施
阶段: 需求 策略: 语言选择 使用不允许出现这种弱点的语言,或提供使这种弱点更容易避免的结构。 例如,许多执行自己的内存管理的Java(如Java和Perl)不受缓冲区溢出的影响。其他语言,如ada和c,通常提供溢出保护,但程序员可以禁用该保护。 请注意,即使语言本身在理论上是安全的,语言与本机代码的接口仍然可能受到溢出的影响。 |
阶段: 架构与设计 策略: 库或者框架 使用一个经过审查的库或框架,它不允许出现这种弱点,或者提供使这种弱点更容易避免的结构。
例如Messier和Viega[Ref-57]的safe c字符串库(safestr)和Microsoft的strsafe.h库[Ref-56]。这些库提供了更安全的易于溢出的字符串处理函数版本。 注意:这不是一个完整的解决方案,因为许多缓冲区溢出与字符串无关。 |
阶段: 编译及链接 策略: 强化编译与链接 使用自动提供保护机制的功能或扩展运行或编译软件,以减轻或消除缓冲区溢出。 例如,某些编译器和扩展提供了内置于编译代码中的自动缓冲区溢出检测机制。示例包括Microsoft Visual Studio/GS标志、Fedora/Red Hat强化源代码gcc标志、StackGuard和Propolice。 有效性: 深度防御 注意: 这不一定是一个完整的解决方案,因为这些机制只能检测某些类型的溢出。此外,攻击仍然可能导致拒绝服务,因为典型的响应是退出应用程序。 |
阶段: 实现 在分配和管理应用程序内存时,请考虑遵守以下规则:
|
阶段: 操作 策略: 强化环境 使用具备随机排列程序可执行文件和库在内存中的位置特性的软件或添加了相关特性的扩展程序来运行或编译软件。因为这会使地址不可预测,所以可以防止攻击者可靠地跳到可利用的代码上。 示例包括地址空间布局随机化(ASLR)[Ref-58][Ref-60]和位置独立可执行文件(Pie)[Ref-64]。 有效性: 深度防御 注意:这不是一个完整的解决方案。但是,它强制攻击者猜测一个未知值,该值会改变每个程序的执行。此外,攻击仍然可能导致拒绝服务,因为典型的响应是退出应用程序。 |
阶段: 操作 策略: 强化环境 使用提供数据执行保护(NX)或其等效功能的CPU和操作系统[Ref-60][Ref-61]。 有效性: 深度防御 注意:这不是一个完整的解决方案,因为缓冲区溢出可以用来覆盖附近的变量,以危险的方式修改软件的状态。此外,它不能用于需要自修改代码的情况。最后,攻击仍然可能导致拒绝服务,因为典型的响应是退出应用程序。 |
阶段: 实现 用支持长度参数的类似函数(如strcpy和strncpy)替换未绑定的copy函数。如果它们不可用,则创建它们。 有效性: 适度 注意:这种方法仍然容易受到计算错误的影响,包括诸如一次错误关闭(CWE-193)和错误计算缓冲区长度(CWE-131)等问题。 |
种属
说明
应用平台
在没有内存管理支持的任何编程语言中,都有可能尝试在内存缓冲区边界之外进行操作,但结果会因语言、平台和芯片架构的不同而大不相同。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。