如果输入是安全的,那么利用一个易受攻击的函数是否可能?

7
假设我有一个存在缓冲区溢出漏洞的代码,如下所示:
int func(const char *str){
    char buffer[100];
    unsigned short len = strlen(str);

    if(len >= 100){
        return -1;
    }
    strncpy(buffer,str,strlen(str));
    return 0; 
}

(摘自这个问题)

如果从另一个函数(而不是用户输入)获取输入,并且str的长度始终小于100,是否有利用此漏洞的方法?

例如:

int main() {
    int user_input;
    if (cin >> user_input) {
        if(user_input == 1)
          func("aaaa");
        else 
          func("bbbb");
    }
}

假设代码中没有其他漏洞。

这只是一个假设性的问题,有什么想法吗?


3
如果字符串的长度始终小于100,则不存在漏洞。 - Anton Savin
1
如果您确定 len 始终小于 100,那么我不明白为什么要使用 if(len >= 100) - Spikatrix
3
@smttsp,你看过你链接的问题的答案了吗?只要str的长度大于65535,无论str来自哪里,都会出现漏洞。 - Anton Savin
2
你的 main 函数存在严重的内存损坏问题。你不能读取字符串字面量的字节,将其转换为非 constchar * 已经被弃用,并应该发出编译器警告。即使你被允许写入 user_input 的字节,该数组也太短了,无法容纳字符串 "1"。此外,使用 == 比较 char 缓冲区可能不会产生你期望的结果。 - 5gon12eder
2
strncpy的参数strlen(str)是一个严重的错误,因为strncpy认为目标缓冲区只能包含没有终止符的字符串,所以总是创建一个非空终止的字符串,如果这段代码正常工作,这可能会被利用。该参数应该是sizeof(buffer)。 - stefaanv
显示剩余6条评论
1个回答

2
简而言之,没有漏洞。每个输入都经过了净化处理 = 没有漏洞。
但这并不意味着你应该将其视为不需要修复。虽然没有物理上的漏洞,但是存在漏洞的潜在风险很大。现在你不能传递超过100个字符的任何内容。但是从几个月后开始呢?你还会记得只能传递长度小于100个字符的输入吗?我觉得不会。
你可以通过以下方式进行修复:
  1. 选择在size_t中保存strlen(但如果变量超过4GB,则无法规避缓冲区溢出)
  2. 使用动态分配的缓冲区,并检查是否成功malloc
  3. 使用strnlensizeof(buffer)而不是strlen
  4. len作为第二个参数(可能很烦人)
使用strncpy(a, b, strlen(b))与使用strcpy(a,b)相同。尽管在if指令中进行了检查,但选择unsigned short来存储它使其毫无价值。最好使用strncpy(a, b, len),以明确len确实需要存在,以防检查被重构掉。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接