ABV.TAINTED
缓冲区溢出 — 受污染的输入中的数组索引超出边界
ABV.TAINTED 可检查由未验证或受污染的输入数据(源自用户或外部设备)引起的缓冲区溢出。此检查器会通过代码标记执行路径,在该代码中,缓冲区溢出中涉及的输入数据未进行验证。
漏洞与风险
缓冲区溢出通常是应用程序攻击和利用的来源。
缓解与预防
要避免发生受污染的输入引起的这些攻击
- 确保在可能发生溢出的行之前插入验证条件
- 考虑到相应输入的所有可能相关的输入属性,包括长度、输入类型、可接受值的完整范围、缺少或多余的输入、语法、相关字段的一致性,以及业务规则遵从性
- 确保已确认范围的最小值和最大值,以避免错误接受负值
漏洞代码示例
复制
#include <stdio.h>
void wrapped_read(char* buf, int count) {
fgets(buf, count, stdin);
}
void TaintedAccess()
{
char buf1[12];
char buf2[12];
char dst[16];
wrapped_read(buf1, sizeof(buf1));
wrapped_read(buf2, sizeof(buf2));
sprintf(dst, "%s-%s\n", buf1, buf2);
}
Klocwork 针对第 15 行生成缓冲区溢出报告,指出未验证的输入用作 dst 的数组索引。数组 dst 的大小定义为 16,但是第 13 和 14 行可能生成 22 个字符的输入,并以 null 终止。在本例中,输入数据尚未针对缓冲区大小进行检查,因此将其视为已受污染。
修正代码示例
复制
#include <stdio.h>
void wrapped_read(char* buf, int count) {
fgets(buf, count, stdin);
}
void TaintedAccess()
{
char buf1[12];
char buf2[12];
char dst[25];
wrapped_read(buf1, sizeof(buf1));
wrapped_read(buf2, sizeof(buf2));
sprintf(dst, "%s-%s\n", buf1, buf2);
}
在该修正代码示例中,dst 的大小已正确定义为 25。
相关检查器
外部指导
- CERT ARR00-C:了解数组的工作原理
- CERT ARR30-C:不形成或使用超出边界的指针或数组下标
- CERT CTR50-CPP:保证容器索引和迭代器在有效范围内
- CERT ENV01-C:不作出关于环境变量大小的假设
- CWE-20:不正确的输入验证
- CWE-99:资源标识符的不当控制(“资源注入”)
- CWE-119:未正确地将操作限制在内存缓冲区边界内
- CWE-121:基于堆栈的缓冲区溢出
- CWE-122:基于堆的缓冲区溢出
- CWE-124:缓冲区欠载(“缓冲区下溢”)
- CWE-125:超出边界的读取
- CWE-129:数组索引验证不当
- CWE-787:超出边界的写入
- CWE-788:访问缓冲区末尾之后的内存位置
- CWE-805:访问长度值错误的缓冲区
- CWE-806:使用源缓冲区的大小访问缓冲区
- CWE-896:无
- OWASP A3:2021 注入
- STIG-ID:APP3510 输入验证不足
- STIG-ID:APP3590.1 应用程序易受缓冲区溢出影响
安全培训
应用程序安全培训材料由 Secure Code Warrior 提供。
扩展
此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 C/C++ 分析。