基于污点分析的JSP Webshell检测(三)

简介: 基于污点分析的JSP Webshell检测

接下来看反射的第一句Class.forName("java.lang.Runtime")

    LDC "java.lang.Runtime"
    INVOKESTATIC java/lang/Class.forName (Ljava/lang/String;)Ljava/lang/Class;
    ASTORE 4

由于调用STATIC方法不需要this然后返回值保存在局部变量表第5位

996d57377cb0e619f96c721a70ac3427_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


这里我给反射三步的LDC分别给上自己的flag做跟踪

注意到LDC命令执行完后保存至栈顶

@Override
public void visitLdcInsn(Object cst) {
    if(cst.equals("java.lang.Runtime")){
        super.visitLdcInsn(cst);
        operandStack.get(0).add("ldc-runtime");
        return;
    }
    if(cst.equals("getRuntime")){
        super.visitLdcInsn(cst);
        operandStack.get(0).add("ldc-get-runtime");
        return;
    }
    if(cst.equals("exec")){
        super.visitLdcInsn(cst);
        operandStack.get(0).add("ldc-exec");
        return;
    }
    super.visitLdcInsn(cst);
}

下一句rt.getMethod("getRuntime")稍微复杂

    ALOAD 4
    LDC "getRuntime"
    ICONST_0
    ANEWARRAY java/lang/Class
    INVOKEVIRTUAL java/lang/Class.getMethod (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
    ASTORE 5


中间主要是多了一步ANEWARRAY操作

6b301a00d0f6b17628e1ceeac82a269e_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


这个染成黄色的过程在代码中如下

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    if(opcode==Opcodes.INVOKEVIRTUAL){
        boolean getMethod = name.equals("getMethod") &&
            owner.equals("java/lang/Class") &&
            desc.equals("(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        if(getMethod){
            if(operandStack.get(1).contains("ldc-get-runtime")){
                super.visitMethodInsn(opcode, owner, name, desc, itf);
                logger.info("-> get getRuntime method");
                operandStack.get(0).add("method-get-runtime");
                return;
            }
        }
    }

下一步是rt.getMethod("exec", String.class)和上面几乎一致,不过数组里添加了元素

    ALOAD 4
    LDC "exec"
    ICONST_1
    ANEWARRAY java/lang/Class
    DUP
    ICONST_0
    LDC Ljava/lang/String;.class
    AASTORE
    INVOKEVIRTUAL java/lang/Class.getMethod (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
    ASTORE 6

这一步几乎重复,就不再画图了,可以看出最后保存到局部变量表第7位

其中陌生的命令有DUP和AASTORE两个,暂不分析,我们在method.invoke中细说


代码中的处理类似

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    if(opcode==Opcodes.INVOKEVIRTUAL){
        boolean getMethod = name.equals("getMethod") &&
            owner.equals("java/lang/Class") &&
            desc.equals("(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        if(getMethod){
            if(operandStack.get(1).contains("ldc-exec")){
                super.visitMethodInsn(opcode, owner, name, desc, itf);
                logger.info("-> get exec method");
                operandStack.get(0).add("method-exec");
                return;
            }
        }
    }

接下来该最关键的一行了:ex.invoke(gr.invoke(null), cmd)

    ALOAD 6
    ALOAD 5
    ACONST_NULL
    ICONST_0
    ANEWARRAY java/lang/Object
    INVOKEVIRTUAL java/lang/reflect/Method.invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
    ICONST_1
    ANEWARRAY java/lang/Object
    DUP
    ICONST_0
    ALOAD 3
    AASTORE
    INVOKEVIRTUAL java/lang/reflect/Method.invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;


第一步的INVOKEVIRTUAL只是得到了Runtime对象

第二步的INVOKEVIRTUAL才是exec(obj,cmd)执行命令的代码

所以我们重点从第二步分析

    ICONST_1
    ANEWARRAY java/lang/Object
    DUP
    ICONST_0
    ALOAD 3
    AASTORE
    INVOKEVIRTUAL java/lang/reflect/Method.invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;

在AASTORE之前的过程如下(防止干扰栈中存在的其他元素没有画出)

  • 之所以要DUP正是因为AASTORE需要消耗一个数组引用
  • 这里的ICONST_1代表初始化数组长度为1

045477ba32ae688465a1ebf352bb55b6_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


AASTORE和INVOKE的过程如下(之前在栈中没有画出的元素都补充到)

7d50fd56a701068a37c2ba78f8a093f8_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


注意其中的细节

  • 消耗一个数组做操作实际上另一个数组引用对象也改变了,换句话说加入了cmd参数


所以我们需要手动处理下AASTORE情况以便于让参数传递下去

    @Override
    public void visitInsn(int opcode) {
        if(opcode==Opcodes.AASTORE){
            if(operandStack.get(0).contains("get-param")){
                logger.info("store request param into array");
                super.visitInsn(opcode);
                // AASTORE模拟操作之后栈顶是数组引用
                operandStack.get(0).clear();
                // 由于数组中包含了可控变量所以设置flag
                operandStack.get(0).add("get-param");
                return;
            }
        }
        super.visitInsn(opcode);
    }

至于最后一步的判断就很简单了

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    if(opcode==Opcodes.INVOKEVIRTUAL){
        boolean invoke = name.equals("invoke") &&
            owner.equals("java/lang/reflect/Method") &&
            desc.equals("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
        if(invoke){
            // AASTORE中设置的参数
            if(operandStack.get(0).contains("get-param")){
                // 如果栈中第3个元素是exec的Method
                if(operandStack.get(2).contains("method-exec")){
                    // 认为造成了RCE
                    logger.info("find reflection webshell!");
                    super.visitMethodInsn(opcode, owner, name, desc, itf);
                    return;
                }
                super.visitMethodInsn(opcode, owner, name, desc, itf);
                logger.info("-> method exec invoked");
            }
        }
    }
    super.visitMethodInsn(opcode, owner, name, desc, itf);
}


其实栈中第2个元素也可以判断下,我简化了一些不必要的操作


总结

代码在:https://github.com/EmYiQing/JSPKiller

后续考虑加入其他的一些检测,师傅们可以试试Bypass手段哈哈

相关文章
|
Java 物联网 Shell
Jsp Webshell在物联网的应用
Jsp Webshell在物联网的应用
111 0
|
存储 Java 关系型数据库
JSP考试质量分析系统myeclipse开发mysql数据库bs框架java编程web网页结构
JSP 考试质量分析系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发,系统主要采用B/S模式开发。
243 1
|
Java 关系型数据库 MySQL
JSP故障诊断分析管理系统myeclipse开发mysql数据库BS模式java编程jdbc
JSP 故障诊断分析管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发,系统主要采用B/S模式开发。
87 1
JSP故障诊断分析管理系统myeclipse开发mysql数据库BS模式java编程jdbc
|
Oracle Java 关系型数据库
基于污点分析的JSP Webshell检测(二)
基于污点分析的JSP Webshell检测
205 0
基于污点分析的JSP Webshell检测(二)
|
安全 Java
基于污点分析的JSP Webshell检测(一)
基于污点分析的JSP Webshell检测
418 0
基于污点分析的JSP Webshell检测(一)
|
安全 Java
浅谈JSP Webshell进阶免杀(三)
浅谈JSP Webshell进阶免杀
702 0
|
算法 JavaScript Java
浅谈JSP Webshell进阶免杀(二)
浅谈JSP Webshell进阶免杀
303 0
|
4月前
|
Java 容器
【学习笔记】Jsp与Servlet技术
【学习笔记】Jsp与Servlet技术
113 0
|
6月前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
41 0
|
6月前
|
供应链 前端开发 Java
JSP+servlet+mybatis+layui服装库存管理系统(大三上学期课程设计)
这篇文章通过一个服装库存管理系统的实例,展示了在Spring Boot项目中使用Ajax、JSON、layui、MVC架构和iframe等技术,涵盖了注册登录、权限管理、用户管理、库存管理等功能,并提供了系统运行环境和技术要求的详细说明。
JSP+servlet+mybatis+layui服装库存管理系统(大三上学期课程设计)