heapdump深度利用之信息泄露篇

前言

Java里有一些渗透场景可以获得堆内存也即是heapdump比如有的应用存在某个功能可以获取heapdumpspringboot/actuator/heapdump也可以获取。但是网上比较多的分析文章讲的都比较浅导致挺多人不知道heapdump里到底有什么东西,这篇文章讲一讲对heapdump进行深入分析获取某些特定信息。

常规信息获取

先讲一下大多数人的分析方式。最早的时候大家都是使用MATjhatjvisualvm然后使用oql语句去查询字符串里的敏感信息。我当时刚接触的时候对这个的分析文章比较少我记得最早讲的比较清楚的文章是下面这篇
https://zen-sec.github.io/fr/java-heapdump-extraction/

这个时期的oql语句主要集中在查询配置信息,以及内存中可能存在的user|pass|email|oss|aksk|jwt|shiro-key等信息后来有人写了自动化的分析工具主要是下面两款
https://github.com/wyzxxz/heapdump_tool
https://github.com/whwlsfb/JDumpSpider

距离工具发布到现在已经有好几年的时间了,然后我发现很多朋友好像已经不会使用oql语句自定义查询信息了,都是使用这两款工具执行一下就结束然后这两款工具有的时候输出没什么敏感的东西就直接结束了不再进行深度利用,我将在下面写一下这两款工具没有覆盖的一些信息获取方式。

深度信息获取

假设我们利用上述两款工具没有获取到什么有用信息还可以使用下面的方式进行利用,这里仅列举出一些案例有其他感兴趣的东西可以自己构造语句查询。使用MAT打开heapdump,主要现在MAT的主要版本需要使用jdk17+才能使用,我jdk环境默认1.8可以使用命令行vm参数指定一个jdk17路径打开
MemoryAnalyzer.exe -vm "C:\Users\admin\.jdks\jbr-17.0.12\bin\javaw.exe"

从这里打开你下载的heapdump然后点击下面图标进行oql查询

查询依赖版本

我们首先可以查看这个应用有什么依赖以及他们具体是什么版本,直接从字符串中搜索DISTINCT用于去重(也可通过类加载器查询)。

复制代码
SELECT DISTINCT toString(s) FROM java.lang.String s WHERE (toString(s) LIKE "file.*\.jar!/")

比如这里发现fastjson依赖在漏洞范围内即可尝试fastjson漏洞。

查询session

这里以springboot默认容器为例tomcat默认的session储存在org.apache.catalina.session.StandardSession中所以可以写出如下oql语句

复制代码
SELECT * FROM org.apache.catalina.session.StandardSession

我这里因为这个网站好像是被很多人扫描了导致尝试了大量无效session总计有1w+,所以需要想办法排除掉一些无效session这种无效session的尝试大多数是扫描器直接访问一个路由然后返回包就会返回一个session这种的话比较好筛选。我们可以注意点每个session实例里都储存了以下信息

根据上面的分析我们可以加一个判断(s.lastAccessedTime - s.creationTime) > 6000也就是最后访问时间需要大于创建时间6秒钟我们即认为是有效session。但是这还不足以判断session是否被设置了访问权限。一般登陆成功后都会使用setAttributesession里设置属性加上一些其他判断我们可以写出如下oql语句直接获取有效的sessionid

复制代码
SELECT s.id.toString() FROM org.apache.catalina.session.StandardSession s WHERE ((s.isValid = true) and (s.attributes != null) and ((s.lastAccessedTime - s.creationTime) > 6000))

有的session属性里甚至会直接存放账号密码

查询http数据包

上面我们查询到了session但是有很多时候并不是使用默认的session鉴权,所有可以获取http数据作为补充。我们知道springboot默认使用tomcat作为容器,经过代码分析已经查阅资料可知可以通过org.apache.coyote.http11.Http11InputBufferorg.apache.tomcat.util.net.SocketBufferHandler分别获取我们heapdump期间或之前尚未处理完的http数据包。

获取请求包

复制代码
SELECT h.byteBuffer.hb.toString() FROM org.apache.coyote.http11.Http11InputBuffer h 

先全选然后右键COPY->Selection即可复制所有数据

获取响应包,最开始以为会记录在Http11OutputBuffer里面经过分析发现Http11OutputBuffer里只记录返回包header数据,完整数据记录需要使用下面的语句查询

复制代码
SELECT rp.writeBuffer.hb.toString() FROM org.apache.tomcat.util.net.SocketBufferHandler rp

获取某些http缓存数据段

复制代码
SELECT DISTINCT bc.buff.toString() FROM org.apache.tomcat.util.buf.ByteChunk bc WHERE (bc.buff != null)

注意这里的数据不和请求包完全重叠,有可能记录一些更早的请求数据.比如这里直接获取了登陆的user、pass从请求包那里查询是没获取到的

查询springboot路由信息

根据之前分析springboot的经验可知路由信息储存在org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#mappingRegistry中我们使用oql语句查询它的实例

复制代码
SELECT * FROM org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry

成功找到路由信息

注意到他最后都储存在java.util.LinkedHashMap$Entry所以我们可以直接使用下面语句获取所有路由

复制代码
SELECT key.toString() FROM java.util.LinkedHashMap$Entry entry WHERE (key.toString() LIKE "/.*")

也可通过MappingRegistration获取路由对应的方法

可以注意到这里已经获取路由对应的方法了且包含参数个数以及参数类型,还差获取参数名研究了一下发现有的情况是可以获取到参数名的。需要之前触发过这个路由,且缓存信息没被删除。

复制代码
select * from org.springframework.web.method.support.HandlerMethodArgumentResolverComposite

总结

本文介绍了Java heapdump的深度分析方法。除了使用常规的自动化工具获取基础敏感信息外,还可以通过自定义OQL语句进行更深入的信息挖掘。这些方法能够在常规工具无法发现敏感信息时,提供更深层次的数据挖掘能力,帮助渗透测试人员获取更多有价值的信息,如登录凭据、API接口、会话数据等。掌握这些技巧可以大大提升heapdump文件的利用价值。

相关推荐
Java水解1 分钟前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
千寻girling4 分钟前
一份不可多得的 《 Python 》语言教程
人工智能·后端·python
南风9995 分钟前
Claude code安装使用保姆级教程
后端
爱泡脚的鸡腿6 分钟前
Node.js 拓展
前端·后端
蚂蚁背大象1 小时前
Rust 所有权系统是为了解决什么问题
后端·rust
子玖3 小时前
go实现通过ip解析城市
后端·go
Java不加班3 小时前
Java 后端定时任务实现方案与工程化指南
后端
心在飞扬3 小时前
RAG 进阶检索学习笔记
后端
Moment3 小时前
想要长期陪伴你的助理?先从部署一个 OpenClaw 开始 😍😍😍
前端·后端·github