SV.BANNED.REQUIRED.ISBAD

已禁用的字符串 IsBad 函数调用

某些 C/C++ 函数被视为是不安全的,因此“已禁用”这些函数。这些函数是:

  • 内存分配函数,如 alloca
  • 字符串串联函数,如 strcat 和 strncat
  • 字符串复制函数,如 strcpy 和 strncpy
  • 获取函数,如 gets 和 _getts
  • isbad 函数,如 IsBadWritePtr
  • 数值转换函数,如 _iota 和 _itow
  • OEM 转换函数,如 CharToOem
  • 路径函数,如 _splitpath 和 makepath
  • 扫描函数,如 scanf
  • 字符串打印函数,如 sprintf 和 snprintf
  • 字符串令牌化函数,如 strtok

SV.BANNED 系列检查器会查找在代码中使用任何已禁用函数的情况。

SV.BANNED.REQUIRED.ISBAD 检查器标记出使用不安全的 IsBad 函数的情况。

漏洞与风险

这些被禁止的函数大都是因为可能导致缓冲区溢出而被禁用。

已禁用的函数的列表既包括 strcpy 和 strcat 之类的函数,也包括很多相对应的“n”函数,例如 strncpy 和 strncat。虽然经常推荐将“n”函数用于替换其匹配的非“n”函数,但是现在它们被视为难以对溢出的缓冲区进行非空终止,而且缺少返回溢出错误的能力。

缓解与预防

禁止使用这些已禁用的 API 可以很好地消除大量代码漏洞。应该使用更安全的版本替换已禁用的函数,或者应该重新设计代码以完全避免使用已禁用的函数。

要避免安全性问题,建议在编译器具有同等安全的功能时,为每一种函数类别使用安全性能相同的函数。在某些情况下,没有替换函数,因此建议重新构建代码的体系结构。IsBad 函数没有替换函数,因为这些函数可能掩盖错误,因此应该重写代码以避免使用这些 API。以下是一些建议:

  • 如果需要避免崩溃,可以使用 __try/__except 隐藏对指针的使用。但是,这样做很容易隐藏 bug,因此应该仅在绝对需要避免崩溃时(例如故障修复代码)执行此操作,以及在查找的数据可能无效又具有合理解释时执行此操作。您也不必捕获所有异常,仅需要捕获您了解的类型。捕获所有异常的效果与使用 IsBad*Ptr 同样糟糕。
  • 对于 IsBadWritePtr 而言,为了确保输出缓冲区是有效的,而且大小足以容纳所需空间,首选方法是使用 memset 填充目标缓冲区。

安全培训

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