来源:香依香偎@闻道解惑
logback
logback
是 log4j
创始人设计的另一个开源日志组件。相比 log4j
,重构了内核的 logback
的优势在于性能更高(关键路径性能提升十倍)、内存占用更小、文档更完善、功能更全面等等。Github
上的数据显示,logback
被八千多个项目所使用,包括 springboot
在内的多个框架已经使用 logback
作为默认的日志组件。
初步分析了一下 logback
库,有一些有趣的发现。
XXE
logback
查找配置文件的函数在ContextInitializer.findURLOfDefaultConfigurationFile()
,首先读取启动参数 logback.configurationFile
来获取配置文件的地址(支持远端 URL
地址)。如果找不到,再去 classpath
下依次查找如下三个文件作为配置文件:
a) logback-test.xml
b) logback.groovy(最新版本似乎不再支持)
c) logback.xml
获取配置文件之后,通过 JoranConfigurator.doConfigure()
(实现在父类的GenericConfigurator.doConfigure()
中) 读取 xml
配置文件,其中调用 SaxEventRecorder.recordEvents()
解析 xml
配置文件时存在 XXE
漏洞。
动态加载
通常情况下,配置文件的这一类 XXE
漏洞并不是大问题,毕竟配置文件只会在初始化的时候加载一次,攻击者没机会触发漏洞。但是 logback
库不一样。只要配置文件中配置了 scan
属性,它就会启动一个 scan task
监控配置文件的变动,支持配置文件变更时的自动加载。
也就是说,我们有机会通过上传覆盖 logback
的 xml
配置文件来触发 XXE
漏洞。触发条件是:
a)
logback
配置文件中配置了scan
属性b)
logback
配置文件是以文件形式保存。
第二个条件是因为代码 convertToFile()
中的一个限制:配置文件 URL
必须以 file://
开始。如果像 springboot
那样,把配置文件保存在 jar
包中,配置文件的 URL
以 jar://
开始,就不会启动实时监控的 scan task
。
JNDI
除了自动更新之外,logback
的配置文件还有一个更强大的功能:利用 JNDI
的 RPC
功能从远端来读取内容,只要在配置文件中配置 <insertFromJNDI>
标签就行了,JNDI的远端路径就配置在这个标签的 env-entry-name
属性中。
梳理一下,如果一个 web
应用满足如下三个条件:
- a)
logback
配置文件以文件形式保存 - b)
logback
配置文件中配置了scan
属性 - c) 有上传接口可以覆盖
logback
配置文件
我们就可以通过覆盖 logback
配置文件,来实现 XXE
攻击,以及 JNDI
的远程 RCE
。
实战
验证一下。
- a) 从
github
上拉取spring-mvc-showcase
项目,将pom.xml
中log4j
的dependency
修改为logback
,增加logback.xml
配置文件,并配置scan
属性。
- b) 通过tomcat运行war包。写一个上传接口,其中存在跨目录文件上传漏洞
- c) 通过上传接口覆盖
logback.xml
文件,增加标签,指定恶意的jndi服务。
- c) 等待一个扫描周期(配置文件中配置的
30
秒)之后,恶意JNDI
地址收到了访问请求,恶意程序成功执行。
JMX
不仅如此,logback
还实现了 jmx
的 MBeans
接口。只要在配置文件中配置 <jmxConfigurator />
的空标签,web
应用就会开放 jmx
端口,供 jconsole
进行连接和调用。
在JMXConfigurator这个MBean中,公开给jconsole调用的接口如下。
验证一下。
- a) 在之前的环境上,我们重新上传一个
logback.xml
,配置上<jmxConfigurator/>
标签。
- b) 等待一个周期查看tomcat进程,发现多了一个39327端口。
- c) 使用
jconsole
连接,无需认证即可登录。可以直接查看tomcat
的管理属性,以及调用tomcat
和logback
提供的MBeans
操作接口。
小结
logback
通过 scan
参数提供了配置文件的动态更新功能。如果可以覆盖这个配置文件,就可以实现XXE、JNDI、jmx等多种攻击方式了。