ThinkPHP本身不执行系统命令,“命令注入”实为开发者在调用exec、shell_exec等函数时未校验用户输入所致;input()过滤对shell元字符无效,必须用escapeshellarg()包裹每个参数或采用白名单控制动词,优先使用PHP原生替代方案。

ThinkPHP 本身不直接执行系统命令,所谓“ThinkPHP 命令注入”实际是开发者在业务逻辑中**调用 exec、shell_exec、system、passthru 或反引号`** 时,未经校验拼接了用户输入导致的漏洞。框架不会帮你拦住这个——它只管 HTTP 层和数据库层,系统调用层完全交由你负责。
为什么 input() 过滤对命令注入完全无效
input() 默认返回原始字符串,即使你加了 'htmlspecialchars' 或 'intval',也只是做字符转义或类型转换,跟 shell 元字符(如 ;、&&、|、`、$()、\)毫无关系。这些符号在 HTML 上无害,但在 shell 中就是执行分隔符。
- 错误示例:
exec('convert -resize ' . input('size') . ' ' . $src . ' ' . $dst)—— 攻击者传size=100x100; rm -rf /就触发命令拼接 -
shell_exec('ls ' . input('path'))—— 传path=/tmp; cat /etc/passwd直接泄露敏感文件 - 哪怕用了
escapeshellarg(),若参数位置错(比如放在命令中间而非末尾),仍可能被绕过
必须用 escapeshellarg(),且只能用于单个参数
escapeshellarg() 是 PHP 唯一能安全包裹用户输入进 shell 命令的函数,但它有严格使用前提:只适用于「整个参数值」,不能用于命令片段或选项名。
- ✅ 正确:
exec('convert -resize ' . escapeshellarg(input('size')) . ' ' . escapeshellarg($src) . ' ' . escapeshellarg($dst)) - ❌ 错误:
exec('convert -resize ' . input('size') . ' ' . escapeshellarg($src) . ' ' . escapeshellarg($dst))——size未包裹,依然可注入 - ❌ 更危险:
exec('convert -' . input('flag') . ' ' . escapeshellarg($src))——flag是选项名,escapeshellarg()不适用,应走白名单
选项名/命令动词类参数必须用白名单硬控制
像 input('format') 要决定用 png 还是 jpg,或者 input('action') 控制执行 zip 还是 unzip,这类字段绝不能靠过滤,必须显式比对。
立即学习“PHP免费学习笔记(深入)”;
- 定义白名单:
$allow_format = ['png', 'jpg', 'webp']; $format = input('format', 'png'); if (!in_array($format, $allow_format)) { throw new \Exception('Invalid format'); } - 命令动词同理:
$action = input('action'); if (!in_array($action, ['compress', 'extract'])) { abort(400); } - 禁止任何形式的“动态拼命令字符串”,例如
$cmd = 'tar -' . input('mode') . 'f ...'——mode是指令开关,不是参数值
能不用 shell 就别用,优先选原生 PHP 替代方案
90% 的常见需求都有纯 PHP 实现,绕过 shell 调用是最彻底的防御。
- 图片处理:用
GD或Imagick扩展替代convert命令 - 压缩解压:用
ZipArchive、PharData替代zip/unzip命令 - 文本处理:用
file_get_contents()+preg_replace()替代sed/awk - 如果必须调用外部程序,确认其支持非 shell 模式(如
proc_open()配合['pipe', 'r']显式传参,不经过 shell 解析)
真正容易被忽略的是:命令注入漏洞往往藏在“辅助功能”里——比如导出 PDF 的钩子、批量生成缩略图的队列任务、日志分析脚本的 Web 管理页。这些地方开发时图快直接拼命令,上线后没人再看,成了长期潜伏点。只要涉及 exec 类函数,就必须逐行检查每个参数来源,没有例外。



















