logback
logback
是 log4j
创始人设计的另一个开源日志组件。相比 log4j
,重构了内核的 logback
的优势在于性能更高(关键路径性能提升十倍)、内存占用更小、文档更完善、功能更全面等等。Github
上的数据显示,logback
被八千多个项目所使用,包括 springboot
在内的多个框架已经使用 logback
作为默认的日志组件。
初步分析了一下 logback
库,有一些有趣的发现。
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运行spring-mvc-showcase的war包。添加一个上传接口,其中存在跨目录文件上传漏洞
c) 通过上传接口覆盖 logback.xml
文件,增加标签,指定恶意的jndi服务。
d) 等待一个扫描周期(配置文件中配置的 30
秒)之后,恶意 JNDI
地址收到了访问请求,恶意程序成功执行。
不仅如此,logback
还实现了 jmx
的 MBeans
接口。只要在配置文件中配置 <jmxConfigurator />
的空标签,web
应用就会开放 jmx
端口,供 jconsole
进行连接和调用。
在JMXConfigurator这个MBean中,公开给jconsole调用的接口如下。
验证一下。
a) 在之前的环境上,我们重新上传一个 logback.xml
,配置上 <jmxConfigurator/>
标签。
b) 等待一个周期查看tomcat进程,发现多了一个39327端口。
c) 使用 jconsole
连接,无需认证即可登录。可以直接查看 tomcat
的管理属性,以及调用 tomcat
和 logback
提供的 MBeans
操作接口。