CERT.PUTENV.AUTO_VARIABLE
不要使用指向自动变量的指针作为参数来调用 putenv()
在 C/C++ 中,POSIX putenv() 函数使用字符串参数来设置环境变量值。putenv() 函数会将指向字符串的指针插入到环境数组中,而不会创建字符串的副本并将指针作为参数提供给该字符串。如果将指向自动存储持续时间缓冲区的指针作为参数提供给 putenv(),则当包含的函数返回并且堆栈内存被回收时,为该缓冲区分配的内存可能会被覆盖。CERT.PUTENV.AUTO_VARIABLE 检查器会标记使用指向自动变量的指针作为参数来调用 putenv() 的情况。
漏洞与风险
如果 putenv() 访问这些自动变量,则环境变量可能会呈现意外的值,并且可能会泄露数据。
漏洞代码示例 1
复制
int func(const char *var) {
char env[1024];
int retval = snprintf(env, sizeof(env),"TEST=%s", var);
if (retval < 0 || (size_t)retval >= sizeof(env)) {
/* Handle error */
}
return putenv(env); // CERT.PUTENV.AUTO_VARIABLE
}
在此不符合要求的示例中,指向自动存储持续时间缓冲区 env 的指针被用作 putenv() 的参数。如果执行此代码,则在 func() 函数已返回并且包含 env 的堆栈帧被回收之后访问 TEST 环境变量时,该变量可能会呈现意外的值。
修正代码示例 1
复制
int func(const char *var) {
static char env[1024]; // Fixed here
int retval = snprintf(env, sizeof(env),"TEST=%s", var);
if (retval < 0 || (size_t)retval >= sizeof(env)) {
/* Handle error */
}
return putenv(env);
}
可以通过使用静态变量来修正该问题。例如,在以上修正代码示例中,变量 env 为静态变量。如果执行此代码,当 func() 退出时,putenv() 将指向有效的内存,而 TEST 环境变量将具有正确的值。
修正代码示例 2
复制
int func(const char *var) {
const char *env_format = "TEST=%s";
const size_t len = strlen(var) + strlen(env_format);
char *env = (char *) malloc(len); // Fixed here
if (env == NULL) {
... return -1;
... }
int retval = snprintf(env, len, env_format, var);
if (retval < 0 || (size_t)retval >= len) {
/* Handle error */
}
if (putenv(env) != 0) {
free(env);
return -1;
}
return 0;
}
此修正代码示例使用堆分配的内存,而不使用自动变量。