命令行注入
问题
与 SQL 注入允许攻击者在数据库上执行任意查询的方式类似,命令行注入允许某人在 Web 服务器上运行不受信任的系统命令。使用不正确安全的服务器,这将使攻击者完全控制系统。
例如,假设脚本允许用户在 Web 服务器上列出目录内容。
<pre>
<?php system('ls ' . $_GET['path']); ?>
</pre>
(在实际应用程序中,可以使用 PHP 的内置函数或对象来获取路径内容。此示例用于简单的安全演示。)
人们希望得到一个类似于/tmp
的 path
参数。但是,如果允许任何输入,path
可能是 ; rm -fr /
。然后,Web 服务器将执行该命令
ls; rm -fr /
并尝试从服务器的根目录中删除所有文件。
解
必须使用 escapeshellarg()
或 escapeshellcmd()
转义所有命令参数。这使得参数不可执行。对于每个参数,还应验证输入值。
在最简单的情况下,我们可以保证我们的例子
<pre>
<?php system('ls ' . escapeshellarg($_GET['path'])); ?>
</pre>
在上一个尝试删除文件的示例之后,执行的命令变为
ls '; rm -fr /'
字符串只是作为参数传递给 ls
,而不是终止 ls
命令并运行 rm
。
应该注意的是,上面的示例现在对命令注入是安全的,但不是来自目录遍历。要解决此问题,应检查规范化路径是否以所需的子目录开头。
PHP 提供了各种执行系统命令的功能,包括 exec
,passthru
,proc_open
,shell_exec
和 system
。所有人都必须仔细验证和转移他们的输入。