这个 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 之前的漏洞),但这不是你的问题。
我有这段代码可以读取用户的输入:
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 之前的漏洞),但这不是你的问题。