前言
在Unix或Linux系统的安全测试和网络防御中,了解如何绕过命令过滤器是非常重要的。今天,我们将探讨几种利用shell命令绕过安全限制的技巧,这些技巧常用于渗透测试中,以检测系统的安全漏洞。
0x00 命令介绍
一般而言,cat /etc/passwd
是一个显示系统用户信息文件的常用命令。但在一些安全设置中,直接执行此命令可能会被系统的安全机制拦截。以下是一些创造性的方法来绕过常见过滤器:
0x01 利用变量截取
cat ${HOME:0:1}etc${HOME:0:1}passwd
这条命令通过利用shell变量截取的特性,将$HOME
变量的第一个字符(通常为/
)用于构建需要的路径,从而避开了直接的字符串匹配过滤。
命令分解
${HOME:0:1}
:
- 这是一个参数扩展的用法,它使用 Bash 的字符串切片功能。
${HOME:0:1}
获取环境变量HOME
的第一个字符。- 对于大多数用户来说,
$HOME
变量通常是/home/username
。因此,${HOME:0:1}
将会得到/
。
2.cat
:
cat
命令用于连接文件并输出其内容到标准输出设备(通常是终端)。- 在这个上下文中,
cat
命令被用来显示文件的内容。
3.连接文件路径:
- 将两个
${HOME:0:1}
的结果(/
)与etc
和passwd
连接,构成/etc/passwd
。 - 这实际上构造出了完整的路径,从而避开了直接写出
/etc/passwd
,这可能是为了绕过某些安全限制或监控工具,这些工具可能会查找直接的路径引用。
0x02 编码和转义
`echo $'cat\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64'`
这个方法通过将命令以十六进制编码的形式展示,从而在不直观地显示命令的同时执行需要的操作。
命令分解
echo $'...'
:- 如之前解释的那样,这个
echo
命令会输出解码后的字符串,即cat /etc/passwd
。
- 如之前解释的那样,这个
- 命令替换 (` ```):
- 使用反引号包围的
echo
命令意味着 shell 首先执行echo
命令,将输出(这里是字符串cat /etc/passwd
)捕获,并将其输出放回原来命令的位置。
- 使用反引号包围的
整体效果
在这个特定的情况下,命令:
`echo $'cat\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64'`
实际上等价于直接在 shell 中输入:
cat /etc/passwd
因为echo
输出的是这个命令的字符串形式,然后通过命令替换,这个字符串被解释并执行为一个新的命令。这将导致/etc/passwd
文件的内容被显示在终端或命令行界面中。
0x03 字符转换
cat $(echo . | tr '!-0' '"-1')etc$(echo . | tr '!-0' '"-1')passwd
使用tr
命令将某些字符转换成其他字符,这种方法可以构造出需要的字符,例如路径分隔符/
,从而绕过对特定字符的过滤。
命令分解
1.$(...)
:
$(...)
是命令替换的一种形式,用于执行其中的命令并将输出替换到外部命令中。这里,它被用两次,每次用于生成单个/
字符。
2.echo . | tr '!-0' '"-1'
:
-
echo .
命令输出一个点字符 (.
)。 -
tr '!-0' '"-1'
是一个
tr
命令,用于转换输入字符。这个特定的转换指令意味着:
- 把
!
到0
(ASCII 表中连续的字符)的所有字符转换成"
到1
(同样是连续的字符序列)。 - 这里的关键在于,ASCII 字符
!
的下一个字符是"
,而"
的下一个字符是#
,依此类推,直到/
被转换成/
本身(因为/
在 ASCII 表中位于!
和0
之间的转换范围内)。
- 把
-
结果,这个
tr
调用将任何字符转换为/
,因为它把.
(并非在!-0
范围内,所以不受转换影响)输出为.
,但在这种使用方式中,. | tr
实际上是用来生成/
。
3.连接文件路径:
- 使用两次命令替换生成的
/
字符与etc
和passwd
连接起来,形成路径/etc/passwd
。
0x04 十六进制转换
cat `xxd -r -ps <(echo 2f6574632f706173737764)`
通过将路径/etc/passwd
以十六进制的形式提供,再通过xxd
命令转换为普通文本,这种方法可以绕开基于文本扫描的过滤。
命令分解
xxd -r -ps
:xxd
是一个十六进制转换工具,常用于生成十六进制转储或反向转换。-r
选项表示逆转换,即将十六进制数据转换回二进制数据。-ps
选项表示从纯十六进制字符串进行解析。
<(echo 2f6574632f706173737764)
:<(...)
是 Bash 的进程替代语法,它创建一个临时的命名管道,其中包含命令的输出。echo 2f6574632f706173737764
将指定的十六进制字符串输出到管道中。这个字符串代表/etc/passwd
的 ASCII 十六进制编码。
- 反引号````:
- 反引号用于命令替换,执行其中的命令,并将输出替换到原位置。
整体命令执行和作用
将上述解释的元素组合起来,此命令执行的过程如下:
echo 2f6574632f706173737764
输出字符串2f6574632f706173737764
。xxd -r -ps
接收这个十六进制字符串,并将其转换回二进制形式,实际上就是解码为/etc/passwd
。cat
命令随后使用解码的路径,即/etc/passwd
,并显示该文件的内容。
0x05 使用Base64编码
echo Y2F0IC9ldGMvcGFzc3dk | base64 --decode | sh
这条命令首先将Base64编码的字符串解码回原始命令,然后通过sh
执行它。
命令分解
echo Y2F0IC9ldGMvcGFzc3dk
:echo
命令用于在标准输出中显示其后跟的字符串。Y2F0IC9ldGMvcGFzc3dk
是字符串cat /etc/passwd
的 Base64 编码形式。
base64 --decode
:base64
是用于数据编码和解码的工具。--decode
或-d
选项用于将 Base64 编码的数据转换回原始数据。
- 管道 (
|
):- 管道用于将一个命令的输出作为另一个命令的输入。在这个例子中,
echo
的输出被传递到base64
命令,然后base64
的输出被传递到sh
命令。
- 管道用于将一个命令的输出作为另一个命令的输入。在这个例子中,
sh
:sh
是一个命令行解释器,用于执行从标准输入读取的命令。- 在这个上下文中,它执行
base64 --decode
解码后的命令。
整体命令执行和作用
将上述解释的元素组合起来,此命令执行的过程如下:
echo
命令输出 Base64 编码的字符串Y2F0IC9ldGMvcGFzc3dk
。base64 --decode
接收这个编码字符串,并将其解码回原始的字符串cat /etc/passwd
。sh
命令接收解码后的命令字符串cat /etc/passwd
,并执行它。
0x06 使用bash的间接引用
cmd='cat /etc/passwd'
bash -c "$cmd"
这种方式通过变量间接执行命令,有时可以绕过简单的命令行监控工具。
命令分解
cmd='cat /etc/passwd'
:- 这行命令定义了一个名为
cmd
的变量,并将字符串cat /etc/passwd
赋值给这个变量。 cat /etc/passwd
是一个常用命令,用于显示/etc/passwd
文件的内容,该文件包含了系统用户的基本信息。
- 这行命令定义了一个名为
bash -c "$cmd"
:bash
是 Unix 和 Linux 系统上常用的命令行解释器。-c
选项告诉bash
从字符串中读取命令并执行。这个字符串是紧接在-c
选项后面的参数。"$cmd"
是对前面定义的变量cmd
的引用,当执行bash -c "$cmd"
时,它被扩展为bash -c "cat /etc/passwd"
。
整体命令执行和作用
组合以上元素,执行这两行命令的过程如下:
- 第一行定义变量
cmd
并存储了命令cat /etc/passwd
。 - 第二行通过
bash -c
使用这个变量,实际上是告诉新启动的 Bash 进程执行cat /etc/passwd
命令。
0x07 利用命令替换
cat $(echo '/etc/pass' | tr ' ' ' ')wd
这条命令利用echo
和tr
来间接构造文件路径,避免了直接写出完整路径。
命令分解
$(...)
:$(...)
是命令替换的一种形式,用于执行其中的命令并将输出替换到原来命令的位置。
echo '/etc/pass' | tr ' ' ' '
:echo '/etc/pass'
命令输出字符串/etc/pass
。tr ' ' ' '
是一个转换命令,用于替换输入中的字符。在这个例子中,它被用来将空格字符转换成空格字符,实际上没有改变输入。这种用法看起来是多余的,但可能是为了说明tr
命令的用法或作为示例的一部分,其真正的作用可能在不同上下文中有所不同。
- 连接字符串:
- 输出的
/etc/pass
通过命令替换被传递给外部的cat
命令。 - 字符串
wd
被直接附加到命令替换的结果之后,形成/etc/passwd
。
- 输出的
整体命令执行和作用
- 执行
echo '/etc/pass' | tr ' ' ' '
结果为/etc/pass
,这一结果通过命令替换$(...)
被插入到cat
命令中。 - 因此,最终执行的命令是
cat /etc/passwd
,它会在终端显示/etc/passwd
文件的内容,该文件包含系统用户的账户信息。
0x08 拆分字符串
part1='/etc/pas'
part2='swd'
cat $part1$part2
这种方法通过将敏感字符串分开来避免直接的字符串匹配。
命令分解
part1='/etc/pas'
:- 这行命令定义了一个名为
part1
的变量,并将字符串/etc/pas
赋值给这个变量。
- 这行命令定义了一个名为
part2='swd'
:- 这行命令定义了一个名为
part2
的变量,并将字符串swd
赋值给这个变量。
- 这行命令定义了一个名为
cat $part1$part2
:cat
是 Unix 和 Linux 系统上用于显示文件内容的命令。$part1
和$part2
是对之前定义的变量的引用。当执行cat $part1$part2
命令时,这两个变量被扩展成它们各自的值,然后拼接在一起。- 所以
$part1$part2
在扩展后变成/etc/paswd
,这实际上与/etc/passwd
相同。
整体命令执行和作用
- 执行这组命令会定义两个变量
part1
和part2
,然后将这两个变量拼接成一个完整的路径/etc/passwd
。 - 使用
cat
命令输出/etc/passwd
文件的内容,这个文件包含了系统用户的账户信息。
0x09 环境变量利用
export PATH_PART='passwd'
cat /etc/$PATH_PART
通过环境变量PATH_PART
隐藏关键文件路径,可能绕过基于静态路径的监控。
命令分解
export PATH_PART='passwd'
:export
是一个用于设置或导出环境变量的命令。通过使用export
,变量PATH_PART
不仅在当前的 shell 会话中可用,也可以在由当前 shell 启动的任何子进程中使用。- 将字符串
'passwd'
赋值给环境变量PATH_PART
。这里的passwd
是/etc/passwd
文件名的一部分。
cat /etc/$PATH_PART
:cat
是一个用于读取文件并输出其内容到标准输出设备的命令。/etc/$PATH_PART
利用了 Bash 的变量替换功能。在这个命令执行时,$PATH_PART
会被替换为其值'passwd'
,从而构造出完整的文件路径/etc/passwd
。
整体命令执行和作用
- 第一行命令设置了一个环境变量
PATH_PART
,使其在当前会话和所有子进程中可用。 - 第二行命令通过将环境变量
PATH_PART
的值拼接到/etc/
路径后面,形成完整的文件路径/etc/passwd
,然后cat
命令被用来显示这个文件的内容。
0x10 利用awk
执行命令
awk 'BEGIN {system("cat /etc/passwd")}'
这条命令使用awk
的system
函数来执行外部命令,有时可以绕过对直接命令执行的监控。
命令分解
awk
:awk
是一个用于文本处理的编程语言,常用于模式匹配、文本分析和复杂的文本操作任务。
BEGIN
:BEGIN
是一个特殊的awk
模式,它在awk
处理任何输入行之前执行。使用BEGIN
块可以在处理输入文件之前设置所需的任何初步操作。
system("cat /etc/passwd")
:system
函数是awk
中用于执行外部系统命令的函数。该函数接受一个字符串参数,该字符串包含要执行的命令。"cat /etc/passwd"
是传递给system
函数的命令,用于显示/etc/passwd
文件的内容。/etc/passwd
文件包含了系统上所有用户的信息,如用户名、用户 ID、组 ID、家目录和 shell。
整体命令执行和作用
- 当执行这条
awk
命令时,它首先进入BEGIN
块,在处理任何输入之前就执行块内的命令。 - 在
BEGIN
块中,system
函数调用cat /etc/passwd
命令,输出/etc/passwd
文件的内容到标准输出。
0x11 利用sed
执行命令
echo | sed 'e cat /etc/passwd'
通过sed
的e
功能(执行替换结果为命令),可以间接执行命令。
命令分解
echo
:echo
命令通常用来输出其后跟随的字符串,但在这里没有提供任何参数,因此它输出一个空行。
- 管道 (
|
):- 管道用于将一个命令的输出作为另一个命令的输入。这里
echo
命令的输出(一个空行)被传递给sed
命令。
- 管道用于将一个命令的输出作为另一个命令的输入。这里
sed 'e cat /etc/passwd'
:sed
是流编辑器,用于对输入进行处理和转换。e
选项在某些版本的sed
中用于将模式空间的内容当作命令执行。这意味着sed
会尝试执行模式空间中的内容作为命令。然而,这种用法并不是所有sed
版本都支持,且当支持时,其正确的用法通常是接收模式空间内的动态内容来执行,而不是静态指定命令。
使用上的问题
- 在大多数标准
sed
实现中(如 GNU sed),不支持e
作为命令执行选项。在支持此功能的sed
版本中(如 GNU sed 4.2.2 之后的版本),e
命令的使用方式通常是处理模式空间内的数据,而不是执行静态指定的命令。因此,这个命令在大多数环境下会因为语法错误而失败。
实际意图
如果目标是利用sed
执行cat /etc/passwd
命令,应该使用不同的方法,如下示例所示(假设使用的sed
版本支持e
):
echo 'cat /etc/passwd' | sed 'e'
在这个修改后的例子中:
echo
输出cat /etc/passwd
字符串。- 此字符串通过管道传递给
sed
。 sed
使用e
执行传入的命令,显示/etc/passwd
文件的内容。
echo | sed 'e cat /etc/passwd'
这个命令的构造在多数情况下是不正确的,因为它误用了sed
的e
选项。正确的使用场景需要根据sed
版本的功能和支持来调整。
0x12 使用perl
执行命令
perl -e 'system("cat /etc/passwd")'
使用Perl的system
函数,可以执行几乎任何命令。
命令分解
perl
:perl
是一种功能丰富的编程语言,广泛用于文本处理、系统管理、网络编程等多种应用。
-e
选项:-e
选项告诉 Perl 解释器直接从命令行执行随后的代码。这允许在没有编写完整脚本文件的情况下快速运行小段代码。
system("cat /etc/passwd")
:system
是 Perl 中用来执行外部命令的函数。它接收一个字符串参数,该字符串包含要执行的命令。- 在这个例子中,传递给
system
的命令是cat /etc/passwd
,这是一个 Unix/Linux 命令,用于显示/etc/passwd
文件的内容。这个文件通常包含系统用户的账户信息,如用户名、用户 ID、组 ID、家目录和 shell。
整体命令执行和作用
- 运行此命令时,Perl 解释器会解析
-e
后面的代码,并执行它。 system("cat /etc/passwd")
调用会导致操作系统执行cat /etc/passwd
命令,其输出将显示在标准输出上,即用户的终端或控制台。
0x13 利用python
执行命令
python -c 'import os; os.system("cat /etc/passwd")'
这条命令使用Python的os.system
方法来执行系统命令,适用于绕过基于特定shell语法的过滤器。
命令分解
python
:python
命令用于启动 Python 解释器。这里用于执行随后的 Python 代码。
-c
选项:-c
选项允许您在命令行中直接运行 Python 代码。它是用于执行单条命令或小段代码的快速方式。
- Python 代码:
import os; os.system("cat /etc/passwd")
:import os
:这部分代码导入 Python 的os
模块,该模块提供了许多与操作系统交互的功能,包括执行一个命令。os.system("cat /etc/passwd")
:os.system()
是os
模块中用于运行外部命令的方法。这个函数接收一个字符串,该字符串包含要在操作系统的命令行中执行的命令。"cat /etc/passwd"
是传递给os.system()
的命令,用于显示/etc/passwd
文件的内容。/etc/passwd
文件包含了系统上所有用户的账户信息。
整体命令执行和作用
- 运行这条命令时,Python 解释器会执行
-c
后面指定的代码。 - 代码中的
os.system("cat /etc/passwd")
调用会触发操作系统执行cat /etc/passwd
命令。 cat /etc/passwd
命令的输出(即文件内容)将显示在终端或命令行界面上。
结语:不断探索,精进攻击技术
通过本文的探讨,我们对绕过命令过滤器的技术有了深入的了解。然而,所介绍的技术仅仅触及了广泛的bypass
方法中的一小部分。在实际的攻击环境中,我们常常会遇到更为复杂多变的防御措施,这要求我们不断创新和灵活地组合不同的命令与代码,以增强bypass
技术的有效性和攻击力。
掌握这些技术不仅是为了突破现有的安全防护,更是为了推动安全研究的深入发展,使我们能够更好地理解安全系统的潜在弱点。通过这种方式,我们不仅能够为安全社区揭示和修补这些漏洞,也能在实际对抗中保持技术的先进性。
攻防之间的博弈永无止境。每一次成功的bypass
都是对我们技术理解的一次深化,每一次失败都是对策略调整的一种启示。让我们继续在法律和道德的框架内探索这一领域,用我们的专业知识和技能推动网络安全技术的进步,共同构建一个更加安全的数字世界。