命令行注入
问题
与 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。所有人都必须仔细验证和转移他们的输入。