NNTS.MUST

非 Null 结尾的字符串导致的缓冲区溢出

在 C 和 C++ 中,C 字符串或 Null 结尾的字符串是以空字符 (\0) 结尾的字符序列。C 字符串的长度通过搜索空字符来确定。

NNTS 系列检查器会查找那些使用了带有并非或可能并非以 Null 终止的字符数组的字符串操纵函数的代码。NNTS.MUST 检查器查找使用字符串操纵函数的代码,其中的字符数组并非以 Null 结尾。

漏洞与风险

Null 结尾曾经导致过安全性问题。例如:

  • 在字符串中插入空字符可能导致意外地将其截断
  • 没有为空字符分配足够的空间或忘记空字符的存在是很常见的 bug
  • 许多程序在将字符串复制到固定大小的缓冲区之前都不会检查长度,当字符串太长时,就会导致缓冲区溢出
  • 无法保存空字符就意味着字符串和二进制数据需要由不同的函数来处理,如果使用了错误的函数就可能导致问题

缓解与预防

为了避免问题:

  • 如果性能约束条件允许,可添加特殊的代码来验证字符串缓冲区是否以 Null 结尾
  • 切换到有界字符串操纵函数,比如 strncpy
  • 检查缓冲区溢出引用通告中所涉及的缓冲区长度

漏洞代码示例

复制
  #include <stdio.h>
  
  int main()
  {
      char buf[8];
      char tgt[1024];
      const char * src = "abcdef";
  
      strncpy(buf, src, 3);
     strcpy(tgt, buf);
     return 0;
 }

Klocwork 针对数组 tgt 第 10 行生成缓冲区溢出报告:因非 Null 结尾的字符串 buf 导致 tgt 缓冲区溢出。针对第 10 行的数组 buf 报告了类似错误。在本示例中,报告了两次数组边界违规,因为读取了 buf 并写入了 tgt。读取和写入都超出了缓冲区的边界(等于或大于 3),其原因是 buf 并非以 Null 结尾(不正确使用 strcpy 将反过来导致此结果)。该代码将导致缓冲区溢出,并造成各种严重的问题。

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。

扩展

此检查器可进行扩展。有关详情,请参阅调整 C/C++ 分析。