SV.TAINTED.INDEX_ACCESS
数组索引中的未经验证的输入
每当从用户或外部环境接受输入的时候,都应该在使用前验证类型、长度、格式和范围。在得到妥善验证之前,数据将被视为已被污染。SV.TAINTED 系列检查器会查找代码中使用已污染数据的情况。
SV.TAINTED.INDEX_ACCESS 检查器标记出那些使用被污染的数据来访问数组的代码。
漏洞与风险
当代码输入未经妥善验证时,攻击者可以精心地将输入编制为并非应用程序所预期的格式。接收意外的输入可能导致控制流被改变、任意的资源控制以及任意的代码执行。通过此类机会,攻击者可以
- 提供无法预料的值并导致程序崩溃
- 导致过度的资源消耗
- 读取机密数据
- 使用恶意输入来修改数据或改变控制流
- 执行任意命令
将用户提供的值用作数组索引可能导致索引越界漏洞。如果漏洞函数允许从任意内存读取或写入任意内存,则它可能导致应用程序不稳定,或遭受精心设计的攻击,出现数据泄露漏洞或代码注入漏洞。
缓解与预防
要避免受污染输入错误:
- 了解所有可能导致不受信任的输入进入软件的区域:参数或自变量、Cookie、读取自网络的输入、环境变量、反向 DNS 查找、查询结果、文件名、数据库以及任何外部系统
- 使用白名单或“已知正确”策略进行输入,而不是仅依赖于黑名单或“已知错误”策略
- 确保对输入的所有相关属性进行验证,包括长度、输入类型、范围、缺失或额外输入、语法以及一致性
- 如果在应用程序的客户端一侧有安全性检查,请确保也在服务器端重复一遍
- 如果应用程序组合来自多个来源的输入,请在组合来源之后再执行验证
漏洞代码示例
复制
void getSize()
{
unsigned num, size;
int i;
scanf("%u %u",&num, &size);
sizes[num - 1] = size;
}
Klocwork 针对第 6 行生成问题报告,表明在第 5 行通过调用 scanf 所接收的、未经验证的整数 num 可能在第 6 行中用于访问数组。在这种情况下,SV.TAINTED.INDEX_ACCESS 检查器标记出用于访问数组的那些可能被污染的数据,这可能被恶意用户利用。
修正代码示例
复制
void getSize()
{
unsigned num, size;
int i;
scanf("%u %u",&num, &size);
if (num > sizeof(sizes)/sizeof(*sizes)) return;
sizes[num - 1] = size;
}
在修正代码示例中,在将整数 num 用于访问数组之前,在第 6 行对其进行了验证。