我刚接触c,正在读一本有关软件漏洞的书,偶然发现了这个缓冲区溢出示例,它提到这可能导致缓冲区溢出。我正在尝试确定情况如何。

int handle_query_string(char *query_string)
{
    struct keyval *qstring_values, *ent;
    char buf[1024];

    if(!query_string) {
        return 0;
    }

    qstring_values = split_keyvalue_pairs(query_string);

    if((ent = find_entry(qstring_values, "mode")) != NULL) {
        sprintf(buf, "MODE=%s", ent->value);
        putenv(buf);
    }
}
我正在密切注意这段代码,因为这似乎是导致缓冲区溢出的地方。
if((ent = find_entry(qstring_values, "mode")) != NULL)
{
    sprintf(buf, "MODE=%s", ent->value);
    putenv(buf);
}

最佳答案

这里非常重要的一点是,您将指向本地变量的指针传递给putenv。当handle_query_string返回时,该缓冲区将不再存在。之后,它将包含垃圾变量。请注意,putenv确实要求传递给它的字符串在程序的其余部分保持不变。从putenv(重点是我的)的文档中:

可以通过使用动态分配进行更正。 char *buf = malloc(1024)代替char buf[1024]另一件事是sprintf(buf, "MODE=%s", ent->value);可能溢出。如果字符串ent->value太长,则会发生这种情况。一种解决方案是改用snprintf

snprintf(buf, sizeof buf, "MODE=%s", ent->value);
这样可以防止溢出,但是仍然可能会引起问题,因为如果ent->value太大而无法容纳在buf中,那么出于明显的原因,buf将不包含完整字符串。
这是纠正两个问题的一种方法:
int handle_query_string(char *query_string)
{
    struct keyval *qstring_values, *ent;
    char *buf = NULL;

    if(!query_string)
        return 0;

    qstring_values = split_keyvalue_pairs(query_string);

    if((ent = find_entry(qstring_values, "mode")) != NULL)
    {
        // Make sure that the buffer is big enough instead of using
        // a fixed size. The +5 on size  is for "MODE=" and +1 is
        // for the string terminator
        const char[] format_string = "MODE=%s";
        const size_t size = strlen(ent->value) + 5 + 1;
        buf = malloc(size);

        // Always check malloc for failure or chase nasty bugs
        if(!buf) exit(EXIT_FAILURE);

        sprintf(buf, format_string, ent->value);
        putenv(buf);
    }
}
由于我们使用的是malloc,因此分配将在函数退出后保留。并且出于相同的原因,我们确保缓冲区事先足够大,因此不必使用snprintf而不是sprintf
从理论上讲,这会导致内存泄漏,除非您对分配的所有字符串都使用free,但是实际上,退出main之前不进行释放很少会成为问题。也许会很高兴知道。
最好知道,即使现在此代码已受到相当的保护,它仍然不是线程安全的。 query_string的内容以及ent->value的内容都可以更改。您的代码没有显示它,但是find_entry很有可能返回指向query_string中某个地方的指针。这当然也可以解决,但是会变得复杂。

关于c++ - 缓冲区溢出示例:为什么此代码很危险?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62946319/

10-11 23:07