环境搭建
主要是服务端和执行端的两个端口,如果与本地端口冲突的话直接改一下端口号即可,还有就是数据库的账号密码配置在这里即可,启动调试,运行XxlJobAdminApplication,XxlJobExecutorApplication两个启动类即可
注意又一个坑点,这里启动的springboot配置jdk推荐1.8,但是可能默认推荐17切换一下即可,别的不需要大动作
访问对应的端口链接信息即可看到后台登陆页面
反序列化
Poc接口部分:POST /xxl-job-admin/api HTTP/1.1
全文查找/api接口关键字,控制器的查找直接看JobApiController这个类即可,因为该接口的访问控制是由它实现的
RequestMapping接口映射为/api,之前碰到的大多数是直接写进参数内的可以理解为@RequestMapping("/api")这种写法,然后就是PermessionLimit访问控制,这里limit的值为false证明权限校验没有被启用,导致接口未授权访问不用携带任何访问信息,后面的api方式实现是处理整个发送的数据流,跟进查看
转到XxlJobDynamicScheduler.invokeAdminService方法内,这里使用jettyServerHandler.handle方法新建了一个Request对象,用来处理传入的数据流到资源的功能
转到jettyServerHandler.handle方法内,这里主要创建Rpc服务根据http传过来的数据完成对象调用,重点关注继续跟进parseRequest(request),这是对象传进来的一个入参点
parseRequest获取http数据量以后转换为字节流,然后判断requestBytes != null && requestBytes.length != 0,这里判断requestBytes 的参数是否为空,字节流长度是否等于0,如果不是进入判断流程内
通过 xxlRpcProviderFactory.getSerializer() 获取一个序列化器对象,然后调用序列化器的 deserialize
方法,将字节数组 requestBytes
反序列化为 XxlRpcRequest
类型的对象,实现了一个序列化数据到对象的整体流程,但是这里还是没有到触发位置
parseRequest处下端点动态调试,打一发poc进入反序列化函数内
可以看到后端是Hessian2Input(is);来处理字节流完成序列化对象调用的,到此整个反序列化流程结束
内存马加载
使用jMG-gui-obf-1.0.8.jar生成冰蝎Filter类型内存马
字节码加载部分使用defineClass加载字节码
内存马注入构造,使用defineClass加载com.google.gso.WebSocketUpgradeDshFilter类,并实例化对象方便后续调用
通过反射调用 Unsafe.defineClass 方法,动态定义一个类实现方法的调用,生成的hessian.ser文件发送到指定服务器下,注入内存马
尝试冰蝎连接成功。不出网情况直接可以打内存马,流量代理方面可以打suo5的内存马,改变一下defineClass加载器即可
实站方面侧重直接ser上线vshell和cs。
原文始发于微信公众号(梅苑安全):Xxl-job Hessian2 反序列化分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论