Command Injection(命令注入)java
执行不可信赖资源中的命令,或在不可信赖的环境中执行命令,都会致使程序以攻击者的名义执行恶意命令。git
Command Injection 漏洞主要表现为如下两种形式:
- 攻击者可以篡改程序执行的命令: 攻击者直接控制了所执行的命令。
- 攻击者可以篡改命令的执行环境: 攻击者间接地控制了所执行的命令。
在这种状况下,咱们着重关注第一种状况,即攻击者控制所执行命令的可能性。 这种形式的 Command Injection 漏洞在如下状况下发生:shell
... String home = System.getProperty("APPHOME"); String cmd = home + INITCMD; java.lang.Runtime.getRuntime().exec(cmd); ...
例 1 中的代码使得攻击者可经过修改系统属性 APPHOME 而指向一个包含恶意版本 INITCMD 的其余路径,从而提升本身在应用程序中的权限,继而为所欲为地执行命令。 因为程序不会验证从环境中读取的值,因此若是攻击者可以控制系统属性 APPHOME 的值,他们就能欺骗应用程序去运行恶意代码从而取得系统控制权。例 2: 如下代码来自一个管理 Web 应用程序,该程序旨在容许用户经过使用围绕 rman 实用程序的批处理文件包启动 Oracle 数据库备份,而后运行 cleanup.bat 脚本删除一些临时文件。 脚本文件 rmanDB.bat 接受一个命令行参数,其中指明了须要执行的备份类型。 因为访问数据库受限,因此应用程序执行备份须要具备较高权限的用户。数据库
... String btype = request.getParameter("backuptype"); String cmd = new String("cmd.exe /K \"c:\\util\\rmanDB.bat "+btype+"&&c:\\utl\\cleanup.bat\"") System.Runtime.getRuntime().exec(cmd); ...
这里的问题是:程序没有对读取自用户的 backuptype 参数作任何验证。 一般状况下,一次调用Runtime.exec() 函数并不会执行多条命令,可是在本例中,程序首先运行了 cmd.exe 指令,进而在一次
调用 Runtime.exec() 后即可以运行多条命令了。 一旦调用了该 shell,它即会心甘情愿地执行用两个与号分隔的多条命令。 若是攻击者传递了一个形式为 "&& del c:\dbms\." 的字符串,那么应用程序将会在执行其余程序指定的命令时执行这些命令。 因为该应用程序的特性,运行该应用程序须要具有与数据库进行交互所需的权限,这就意味着攻击者注入的任何命令都将经过这些权限得以运行。 例 3: 如下代码来自一个 Web 应用程序。经过该应用程序,用户能够访问可以更新其系统密码的接口。 在特定的网络环境中更新密码时,其中的一个步骤就是在 /var/yp 目录中运行 make 命令,下面显示了此步骤的代码。安全
... System.Runtime.getRuntime().exec("make"); ...
这里的问题在于程序没有在它的构造中指定一个绝对路径,而且没能在执行Runtime.exec() 调用前清除它的环境变量。 若是攻击者可以修改 $PATH 变量,把它指向名为 make 恶意二进制代码,程序就会在其指定的环境下执行,而后加载该恶意二进制代码,而非本来指望的代码。 因为应用程序自身的特性,运行该应用程序须要具有执行系统操做所需的权限,这意味着攻击者会利用这些权限执行本身的 make,从而可能致使攻击者彻底控制系统。 此种类来源于 Cigital Java Rulepack。 http://www.cigital.com/securitypack/网络
应当禁止用户直接控制由程序执行的命令。 在用户的输入会影响命令执行的状况下,应将用户输入限制为从预约的安全命令集合中进行选择。 若是输入中出现了恶意的内容,传递到命令执行函数的值将默认从安全命令集合中选择,或者程序将拒绝执行任何命令。 在须要将用户的输入用做程序命令中的参数时,因为合法的参数集合实在很大,或是难以跟踪,使得这个方法一般都不切实际。 开发者一般的作法是使用黑名单。 在输入以前,黑名单会有选择地拒绝或避免潜在的危险字符。 可是,任何一个定义不安全内容的列表都极可能是不完整的,而且会严重地依赖于执行命令的环境。 较好的方法是建立一份白名单,容许其中的字符出如今输入中,而且只接受彻底由这些经承认的字符组成的输入。 攻击者能够经过修改程序运行命令的环境来间接控制这些命令的执行。 咱们不该当彻底信赖环境,还需采起预防措施,防止攻击者利用某些控制环境的手段进行攻击。 不管什么时候,只要有可能,都应由应用程序来控制命令,并使用绝对路径执行命令。 若是编译时尚不了解路径(如在跨平台应用程序中),应该在执行过程当中利用可信赖的值构建一个绝对路径。 应对照一系列定义有效值的常量,仔细地检查从配置文件或者环境中读取的命令值和路径。 有时还能够执行其余检验,以检查这些来源是否已被恶意篡改。 例如,若是一个配置文件为可写,程序可能会拒绝运行。 若是可以预先得知有关要执行的二进制代码的信息,程序就会进行检测,以检验这个二进制代码的合法性。 若是一个二进制代码始终属于某个特定的用户,或者被指定了一组特定的访问权限,这些属性就会在执行二进制代码前经过程序进行检验。 尽管可能没法彻底阻止强大的攻击者为了控制程序执行的命令而对系统进行的攻击,但只要程序执行外部命令,就务必使用最小受权原则: 不给予超过执行该命令所必需的权限。函数