常见漏洞验证121 条

命令注入修复视角

修复核心是避免经过 shell 解析:优先用语言原生 API;必须调用外部程序时以参数数组传递,并对取值做白名单校验。

命令注入为什么难修

命令注入的根因是用户输入拼接进了被 shell 解释的字符串:一旦输入里带上分隔符、管道或反引号,命令结构就被改变。修复的核心思路不是「过滤更多字符」,而是让输入根本不经过 shell 解析——优先用语言内置库完成同样的事,必须调用外部程序时以参数数组传递,输入值只作为参数而非命令文本。对确实无法避免的参数,再叠加白名单与规范化校验。

基本信息

首选方案用语言内置库替代 shell 命令(如文件操作用标准库)
次选方案以参数数组调用外部程序,不经过 shell 拼接
兜底措施对文件名、路径、数量类参数做白名单与规范化
适用语言Java ProcessBuilder、Python subprocess 列表形式、PHP 数组形式
不推荐字符串拼接后交给 shell 解释,包括 sh -c 形式的包装

典型使用场景

  • 代码审计中定位命令执行调用点的修复方案设计
  • 修复评审时判断「过滤特殊字符」是否已足够
  • 设计图片处理、文档转换等必须调用外部程序的模块
  • 评审运维脚本与定时任务中的参数传递方式
  • 判断第三方库内部的命令封装是否引入了新的注入面

调用方式对比

调用方式对比
不安全:把输入拼进命令字符串交给 shell 解释
       参数值中的分隔符、管道与替换语法会改变命令结构
安全:  以参数数组调用,输入只作为独立参数传入
        例如 ['convert', 源文件, 目标文件],不经过 shell
更强:  用语言内置库完成同样功能,彻底消除外部程序调用
兜底:  对参数做白名单校验,并拒绝控制字符与路径穿越写法

修复方案对照

方案有效性注意点
改用语言内置库高需要确认功能等价,注意字符编码与超时处理
参数数组调用高不能同时使用 shell=True 之类的开关
白名单校验参数值中依赖校验完整,只适合取值可枚举的场景
黑名单过滤特殊字符低编码、通配符与换行等写法多样,容易绕过
黑名单过滤特殊字符不可靠:不同 shell、不同编码与不同调用层次对字符的解释都不一样,应从根本上避免拼接。
外部程序自带解析的场景要单独确认:某些工具会把参数当成命令串再解析一次,这类「二次解析」需要按工具文档禁用或严格校验。

易错点

  • 只过滤输入中的符号,未改调用方式:一旦出现编码绕过或新分隔符写法,防护立即失效
  • 忽略外部程序的二次解析:部分工具会把参数值再当命令串解析,需要在调用侧关闭该行为
  • 框架与工具库的封装未纳入排查:多层封装的调用链中任何一层拼接都会重新引入风险
  • 把 sh -c 形式当安全写法:包装一层 shell 后,注入面与原写法没有区别

数据来源与参考

  • OWASP Cheat Sheet:OS Command Injection Defense
  • CWE-78
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌