SV.TAINTED.CALL.BINOP
通过函数调用在二进制运算中使用未经验证的整数
从用户或外部环境接受输入数据时,应在使用之前验证类型、长度、格式和范围。在未经正确验证之前,将其视为已污染数据。SV.TAINTED 系列检查器会查找代码中使用已污染数据的情况。
SV.TAINTED.BINOP 检查器会标记在算术二进制运算(例如加、减或乘)中通过函数调用使用已污染数据的代码。
漏洞与风险
如果代码的整数数据输入未经过正确验证即用作二进制运算的操作数,可能导致整数溢出或环绕。攻击者可利用此潜在问题修改正常控制流,从而导致出乎意料的程序行为。在最坏的情况下,攻击者可以:
- 提供无法预料的值并导致程序崩溃
- 导致过度的资源消耗
- 读取机密数据
- 使用恶意输入来修改数据或改变控制流
- 执行任意命令
缓解与预防
要避免受污染输入错误:
- 了解不受信任的输入进入您软件的所有可能区域:参数或自变量、cookie、读取自网络的输入、环境变量、反向 DNS 查找、查询结果、文件名、数据库以及任何外部系统;
- 使用白名单或“已知正确”策略进行输入,而不是仅依赖于黑名单或“已知错误”策略;
- 确保对输入的所有相关属性进行验证,包括长度、输入类型、范围、缺失或额外输入、语法以及一致性;
- 如果应用程序的客户端有安全性检查,请确保在服务器端也进行一次安全性检查;
- 如果应用程序将来自多个来源的输入组合在一起,请在组合来源之后执行验证。
漏洞代码示例
复制
int get_altitude();
void set_altitude(int);
int get_untrusted() {
int i;
scanf("%d", &i);
return i;
}
extern const int max_altitude;
int get_new_altitude(int shift) {
int current_altitude = get_altitude();
return current_altitude + shift;
}
void increase_altitude() {
int shift = get_untrusted();
if (shift > 0) {
int new_altitude = get_new_altitude(shift);
if (new_altitude < max_altitude) {
set_altitude(new_altitude);
}
}
}
在上例中,攻击者可为变量 new_altitude 提供任意大的值。如果第 14 行中的二进制运算溢出,可导致第 20 行中的变量 new_altitude 的值为负值,并出现意外的程序行为。
Klocwork 在第 20 行报告 SV.TAINTED.BINOP 缺陷,指出:“在第 18 行中接收自 get_untrusted 的未经验证的整数值 shift 通过在第 20 行调用 get_new_altitude 用作二进制运算符的操作数”。
修正代码示例
复制
int get_altitude();
void set_altitude(int);
int get_untrusted() {
int i;
scanf("%d", &i);
return i;
}
extern const int max_altitude;
extern const int max_trusted_shift;
int get_new_altitude(int shift) {
int current_altitude = get_altitude();
return current_altitude + shift;
}
void increase_altitude() {
int shift = get_untrusted();
if (shift > 0 && shift < max_trusted_shift) {
int new_altitude = get_new_altitude(shift);
if (new_altitude < max_altitude) {
set_altitude(new_altitude);
}
}
}
Klocwork 检查器不会在此处生成缺陷报告,因为整数值 shift 在用于二进制运算之前在第 20 行中已经过验证。