当前位置:首页 > 百科 > 命令执行漏洞 正文

命令执行漏洞

时间:2026-10-17 05:07:22 来源:力不从心网

去年某次攻防演练,命令一个边缘业务系统成了突破口。执行前端是漏洞个普普通通的文件上传页面,后端却把用户传上来的命令文件名直接拼进了系统命令里。攻击者构造了一个带分号的执行文件名,服务器乖乖执行了三条命令——第一条是漏洞上传,后两条是命令反弹shell。整个过程不到两秒。执行这就是漏洞命令执行漏洞,一个在代码里看起来"只是命令调个系统命令而已"的疏忽,在攻击者手里就是执行直接接管服务器的钥匙。

它的漏洞本质很简单:应用程序把不可信的数据当作系统命令的一部分来执行。PHP里的命令system()、exec()、执行shell_exec(),漏洞Java里的Runtime.exec(),Python里的os.system()——这些函数本身没有错,错的是喂给它们的数据没有经过任何过滤。就像你把家里的钥匙交给一个陌生人,还告诉他保险箱在哪。

常见的注入点比想象中多。文件上传时对文件名做处理、图片压缩时调用ImageMagick、网络诊断功能里ping一个用户输入的IP、甚至日志分析脚本里用grep去搜用户提交的关键词。开发者的思路通常是"这个参数用户控制不了"或者"我做了白名单",但白名单本身写错了的情况比比皆是。我见过一个系统,过滤了;和|,却忘了%0a换行符照样能截断命令。

利用方式也没那么神秘。Linux下分号、管道符、反引号、$()都是命令连接符。Windows下&和|同样好使。更隐蔽的是命令替换——`whoami`这种写法在很多过滤器眼皮底下溜过去。如果目标没回显,盲注技巧就派上用场了:用sleep判断命令是否执行,用curl把结果外带到自己的服务器,或者写个文件到web目录再访问。方法不高级,管用就行。

真正让人头疼的是修复。很多团队第一反应是加黑名单,过滤;、|、&这些字符。这基本等于没修。编码绕过、变量拼接、通配符替代,绕过手法一抓一大把。正确的做法是尽量避免调用系统命令——PHP有glob()就别用ls,有file_get_contents()就别用cat。实在绕不开,用escapeshellarg()对每个参数单独转义,而不是自己写正则。

还有一种情况容易被忽略:即使参数转义了,命令本身也可能被操纵。比如ping命令,你以为用户只能传IP,但-c 100000这种参数注入照样能让服务器资源耗尽。参数注入和命令注入是两回事,防御手段也不同。

从防御纵深的角度看,命令执行漏洞的杀伤力在于它直接跳过了应用层的一切逻辑。SQL注入还要绕WAF、猜表名,命令执行一旦成功,whoami一跑,权限清清楚楚。如果Web服务以root运行——这种情况至今不少见——那就直接结束了。所以容器化部署、最小权限运行、禁用危险函数,这些老生常谈的东西,在命令执行面前不是最佳实践,是底线。

代码审计时看到system($_GET['cmd'])这种写法,谁都知道有问题。但真实环境里更多的是exec("convert ".$uploadedFile." output.jpg")这种看起来人畜无害的代码。漏洞从来不在显眼的地方,它藏在开发者觉得"这里不可能出问题"的自信里。

推荐内容