携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情
命令注入
什么是命令注入?
命令注入是一种网络攻击,涉及在主机操作系统 (OS) 上执行任意命令。通常,威胁参与者通过利用应用程序漏洞(如输入验证不足)来注入命令。
命令注入的工作原理 – 任意命令
例如,威胁参与者可以使用不安全的用户数据传输(如 Cookie 和表单)将命令注入 Web 服务器上的系统 shell 中。然后,攻击者可以利用易受攻击的应用程序的权限来危害服务器。
命令注入有多种形式,包括直接执行 shell 命令、将恶意文件注入服务器的运行时环境以及利用配置文件(如 XML 外部实体 (XXE))中的漏洞。
代码注入与命令注入
代码注入是涉及注入由应用程序解释/执行的代码的任何类型的攻击的通用术语。这种类型的攻击利用了对不受信任的数据输入的错误处理。这是由于缺乏适当的输入/输出数据验证而成为可能的。
代码注入攻击的一个关键限制是它们仅限于它们所针对的应用程序或系统。如果攻击者可以将 PHP 代码注入应用程序并执行该应用程序,则恶意代码将受到 PHP 功能和主机上授予 PHP 的权限的限制。
命令注入通常涉及在系统 shell 或环境的其他部分中执行命令。攻击者扩展了易受攻击应用程序的默认功能,使其能够将命令传递到系统 shell,而无需注入恶意代码。在许多情况下,命令注入使攻击者能够更好地控制目标系统。
命令注入漏洞示例
下面是应用程序漏洞如何导致命令注入攻击的三个示例。这些示例基于 OWASP 提供的代码。
示例 1:文件名作为命令参数
下面是一个程序示例,该程序允许远程用户查看文件的内容,而不能修改或删除该文件。该程序以 root 权限运行:
int main(char* argc, char** argv) {
char cmdCMD_MAX] = "/usr/bin/cat ";
strcat(cmd, argv1]);
system(cmd);
}
尽管该程序被认为是无害的 - 它只允许对文件的只读访问 - 但它启用了命令注入攻击。如果攻击者传递的字符串不是文件名,而是类似以下内容的字符串:
“;rm -rf /”
对 system() 的调用将无法执行,然后操作系统将执行根磁盘分区的递归删除。
示例 2:操作 APPHOME 环境变量
以下代码段使用 $APPHOME 环境变量确定某个应用程序的安装目录,并在该目录中运行脚本。
...
char* home=getenv("APPHOME");
char* cmd=(char*)malloc(strlen(home)+strlen(INITCMD));
if (cmd) {
strcpy(cmd,home);
strcat(cmd,INITCMD);
execl(cmd, NULL);
}
…
问题是代码不验证初始化脚本的内容。如果攻击者设法使用恶意版本的脚本将$APPHOME变量修改为其他路径,则此代码将运行恶意脚本。这构成了命令注入攻击。
示例 3:操作$PATH变量
以下代码可用于更改服务器上的密码的程序,并使用 root 权限运行:
system("cd /var/yp && make &> /dev/null");
此代码的问题部分是 make 的使用。虽然攻击者无法更改代码本身,但由于它不接受用户输入,因此他们可以修改$PATH变量。这可能导致命令在攻击者控制的不同路径中执行。在另一个文件夹路径中,攻击者可以植入恶意版本的 make 二进制文件。
由于父程序具有 root 权限,因此恶意版本的 make 现在将使用 root 权限运行。
所有这三个示例的底线是,任何调用 system 级函数(如 system() 和 exec())的命令都可以将其 root 权限借给在其中运行的其他程序或命令。
命令注入方法
以下是一些通常会导致命令注入攻击的漏洞。
任意命令注入
某些应用程序可能允许用户运行任意命令,并按原样运行这些命令到基础主机。
任意文件上传
如果应用程序允许用户上载具有任意文件扩展名的文件,则这些文件可能包含恶意命令。在大多数Web服务器上,将此类文件放在webroot中将导致命令注入。
不安全的序列化
服务器端代码通常用于反序列化用户输入。如果在未正确验证的情况下执行反序列化,则可能导致命令注入。
服务器端模板注入 (SSTI)
许多 Web 应用程序使用服务器端模板来生成动态 HTML 响应。这使得攻击者能够插入恶意的服务器端模板。当用户输入以不安全的方式嵌入到模板中,并且在服务器上远程执行代码时,就会发生SSTI。
XML 外部实体注入 (XXE)
XXE 发生在使用配置不当的 XML 分析器来分析用户控制的 XML 输入的应用程序中。此漏洞可能导致敏感数据泄露、服务器端请求伪造 (SSRF) 或拒绝服务攻击。
命令注入预防
您可以实施以下几种做法来防止命令注入:
-
避免系统调用和用户输入 - 防止威胁参与者在 OS 命令中插入字符。
-
设置输入验证 - 防止 XSS 和 SQL 注入等攻击。
-
创建白名单 - 可能的输入,以确保系统仅接受预先批准的输入。
-
仅使用安全 API — 执行 execFile() 等系统命令时
-
安全地 使用 execFile() — 防止用户获得对程序名称的控制权。还应将用户输入映射到命令参数,以确保用户输入不会按原样传递到程序执行中。