这个 C 用户输入代码容易受到攻击吗?

Is this C user input code vulnerable?

我有这段代码可以读取用户的输入:

unsigned int readInput(char * buffer, unsigned int len){
    size_t stringlen = 0;
    char c;
    while((c = getchar()) != '\n' && c != EOF){
        if(stringlen < (len-1)){
            buffer[stringlen] = c;
            stringlen++;
        }
    }
    buffer[stringlen+1] = '\x00';
    return stringlen;
}

char * buff 的大小已设置为 len 并且已被 memset 包含“0”。此代码是否容易受到任何漏洞攻击?

根据平台的不同,unsigned int 可能太小而无法容纳数字 13194139533312。在 C 中,您应该始终使用 size_t 作为缓冲区大小,不这样做可能是一个漏洞,是的。

另外,当然 getchar() 不会 return char,所以那也坏了。

我会说 "yes",该代码易受攻击。

您的代码可能会越界并使数组元素未初始化:

char buf[10];  // uninitialized!

readInput(buf, 10);   // feed 12 TB of data

这有未定义的行为,因为您写入 buf[10]

readInput(buf, 10);  // feed 8 bytes of data

strlen(buf);

这有未定义的行为,因为您读取了未初始化的值 buf[8]

错误在于您分配空终止符的方式使用了错误的索引。它应该说:

buffer[stringlen] = '[=12=]';
//     ^^^^^^^^^

因为您计算 len - 1,您的代码还应该有一个先决条件,即 len 必须严格为正。这是明智的,因为您承诺会生成一个以 null 结尾的字符串。

假设缓冲区分配了 len 字节,最明显的问题是:

buffer[stringlen+1] = '\x00';

这是因为循环可以在 stringlen 等于 len-1 时退出,因此您正在写入 buffer[len]。但是,您应该只写入不超过 len-1.

的索引

所以让我们按如下方式解决这个问题:

buffer[stringlen] = '\x00';

这是您真正想要的,因为您还没有写信给 buffer[stringlen]

一个更微妙的错误是,如果 len 为 0(您可能会说这永远不会发生),则 len-1 是 MAXINT,因此 (stringlen < (len-1)) 始终为真。因此,代码将始终在 0 长度缓冲区上发生缓冲区溢出。

你的问题是代码是否容易受到攻击。答案是否定的,它不脆弱,当然不是脆弱性的通用定义。

这是一些未知输入(可能来自对手)和缓冲区之间的接口。您已正确包含防止缓冲区溢出的机制,因此您的代码是安全的。 [我们在这里假设从 getchar() 开始的所有内容都不是您问题的主题]。

代码是否按预期工作是另一回事,(其他人已经指出了终止 NULL 之前的漏洞),但这不是你的问题。