【缺陷周话】第24期:在 scanf 函数中没有对 %s 格式符进行宽度限制
字数 902 2025-08-18 11:37:57

在scanf函数中没有对%s格式符进行宽度限制的安全缺陷分析

1. 缺陷概述

scanf()函数是C语言中常用的输入函数,当使用%s格式说明符时,如果没有对最大字段宽度进行限制,可能会导致缓冲区溢出漏洞。

相关函数

  • scanf()
  • vscanf()
  • fscanf()
  • vsscanf()

2. 函数原型

int scanf(const char *restrict format, ...);

3. 格式说明符

常见格式说明符包括:

  • %c - 字符
  • %d - 十进制整数
  • %s - 字符串
  • %o - 八进制整数
  • %p - 指针
  • %x/%X - 十六进制整数

4. %s格式符的行为

  • 接收输入字符串并放入字符数组中
  • 输入时以非空白字符串开始
  • 以遇到第一个空白字符结束
  • 匹配非空字符时使用字符指针指向数组

5. 安全风险

当使用%s格式说明符而没有限制最大字段宽度时:

  1. 输入长度可能超出目标缓冲区长度
  2. 导致缓冲区溢出
  3. 可能覆盖其他数据区

6. 示例代码分析

缺陷代码示例

fscanf(stream, "%s", a);  // 没有对%s进行宽度限制

修复后的代码

fscanf(stream, "%100s", a);  // 限制最大宽度为100字符

7. 检测方法

使用静态代码分析工具(如360代码卫士)可以检测此类问题:

  • 检测等级:高
  • 检测目标:查找未限制宽度的%s格式符使用

8. 防御措施

  1. 限制宽度:在使用%s时始终指定最大字段宽度

    scanf("%99s", buffer);  // 对于100字节的缓冲区
    
  2. 使用更安全的替代函数

    • fgets() + sscanf()
    • 特定平台的"安全"版本(如scanf_s
  3. 静态代码分析

    • 使用自动化工具定期扫描代码
    • 在开发流程中集成安全检测

9. 最佳实践

  1. 避免在关键代码中使用scanf()系列函数
  2. 如果必须使用,确保:
    • 为所有%s格式符指定最大宽度
    • 宽度值应小于目标缓冲区大小(留出空字符空间)
  3. 进行边界测试,验证输入处理逻辑
  4. 在代码审查中特别检查输入处理函数的使用

10. 相关安全缺陷

其他类似的输入处理安全问题包括:

  • 缓冲区上溢/下溢
  • 命令注入
  • SQL注入
  • 路径遍历
  • 整数溢出

11. 总结

scanf()系列函数中的%s格式符如果不加宽度限制,是常见的缓冲区溢出漏洞来源。开发人员应当:

  1. 始终为%s指定最大宽度
  2. 考虑使用更安全的输入函数
  3. 通过自动化工具和代码审查确保安全性
  4. 遵循安全编码规范处理所有用户输入
在scanf函数中没有对%s格式符进行宽度限制的安全缺陷分析 1. 缺陷概述 scanf() 函数是C语言中常用的输入函数,当使用 %s 格式说明符时,如果没有对最大字段宽度进行限制,可能会导致缓冲区溢出漏洞。 相关函数 scanf() vscanf() fscanf() vsscanf() 2. 函数原型 3. 格式说明符 常见格式说明符包括: %c - 字符 %d - 十进制整数 %s - 字符串 %o - 八进制整数 %p - 指针 %x / %X - 十六进制整数 4. %s格式符的行为 接收输入字符串并放入字符数组中 输入时以非空白字符串开始 以遇到第一个空白字符结束 匹配非空字符时使用字符指针指向数组 5. 安全风险 当使用 %s 格式说明符而没有限制最大字段宽度时: 输入长度可能超出目标缓冲区长度 导致缓冲区溢出 可能覆盖其他数据区 6. 示例代码分析 缺陷代码示例 修复后的代码 7. 检测方法 使用静态代码分析工具(如360代码卫士)可以检测此类问题: 检测等级:高 检测目标:查找未限制宽度的 %s 格式符使用 8. 防御措施 限制宽度 :在使用 %s 时始终指定最大字段宽度 使用更安全的替代函数 : fgets() + sscanf() 特定平台的"安全"版本(如 scanf_s ) 静态代码分析 : 使用自动化工具定期扫描代码 在开发流程中集成安全检测 9. 最佳实践 避免在关键代码中使用 scanf() 系列函数 如果必须使用,确保: 为所有 %s 格式符指定最大宽度 宽度值应小于目标缓冲区大小(留出空字符空间) 进行边界测试,验证输入处理逻辑 在代码审查中特别检查输入处理函数的使用 10. 相关安全缺陷 其他类似的输入处理安全问题包括: 缓冲区上溢/下溢 命令注入 SQL注入 路径遍历 整数溢出 11. 总结 scanf() 系列函数中的 %s 格式符如果不加宽度限制,是常见的缓冲区溢出漏洞来源。开发人员应当: 始终为 %s 指定最大宽度 考虑使用更安全的输入函数 通过自动化工具和代码审查确保安全性 遵循安全编码规范处理所有用户输入