标准答案
- 能不用 shell 就不用 shell,使用 execve 或语言运行时的参数数组传递固定程序和独立参数。
- 必须使用 shell 时要固定脚本、严格允许列表、正确转义并限制运行用户、工作目录、环境和文件系统权限。
- 命令超时、输出大小、退出码和信号都要受控,不能只防止分号而忽略重定向、替换、管道和编码差异。
- 安全验证要覆盖恶意输入、异常字符、超时和权限边界,并记录可审计但不泄露敏感参数的执行信息。
题目解析
命令注入的根因是把数据放进了会再次解析的 shell 语法环境。分号和 && 只是其中一部分,命令替换、重定向、管道、换行、变量展开、通配符和编码差异都可能改变语义;跨语言手写转义很难覆盖所有组合。
优先使用固定可执行文件加参数数组,禁用 shell;必须调用 shell 时也要固定脚本、参数允许列表、工作目录、环境和资源限制。执行账户应非 root,设置超时、输出上限和审计字段,并用恶意输入、异常字符和权限边界测试。
常见误区
- 误区:只过滤 ; 或 &&。改正:避免 shell 解析,使用参数化调用和允许列表。
- 误区:用 root 运行外部命令。改正:使用最小权限账户和必要的 capability,隔离可写目录。
- 误区:把用户输入写入临时脚本后直接执行。改正:固定脚本内容,把输入作为受约束参数传递并限制执行能力。