命令行注入

问题

与 SQL 注入允许攻击者在数据库上执行任意查询的方式类似,命令行注入允许某人在 Web 服务器上运行不受信任的系统命令。使用不正确安全的服务器,这将使攻击者完全控制系统。

例如,假设脚本允许用户在 Web 服务器上列出目录内容。

<pre>
<?php system('ls ' . $_GET['path']); ?>
</pre>

(在实际应用程序中,可以使用 PHP 的内置函数或对象来获取路径内容。此示例用于简单的安全演示。)

人们希望得到一个类似于/tmppath 参数。但是,如果允许任何输入,path 可能是 ; rm -fr /。然后,Web 服务器将执行该命令

ls; rm -fr /

并尝试从服务器的根目录中删除所有文件。

必须使用 escapeshellarg()escapeshellcmd() 转义所有命令参数。这使得参数不可执行。对于每个参数,还应验证输入值。

在最简单的情况下,我们可以保证我们的例子

<pre>
<?php system('ls ' . escapeshellarg($_GET['path'])); ?>
</pre>

在上一个尝试删除文件的示例之后,执行的命令变为

ls '; rm -fr /'

字符串只是作为参数传递给 ls,而不是终止 ls 命令并运行 rm

应该注意的是,上面的示例现在对命令注入是安全的,但不是来自目录遍历。要解决此问题,应检查规范化路径是否以所需的子目录开头。

PHP 提供了各种执行系统命令的功能,包括 execpassthruproc_openshell_execsystem。所有人都必须仔细验证和转移他们的输入。