近日,Apache Tomcat爆出两个安全绕过漏洞,Apache Tomcat 7,8,9多个版本受到影响。攻击者可以利用这个问题,绕过某些安全限制来执行未经授权的操作。本篇文章只对CVE-1318至05年进行简要分析。
CVE-1318至05年
CVE-二○一八年至1304年
从造成的影响方面来讲,都是鸡肋。从原理上讲有点像,基本可以认为是同一个。从分析角度来讲,这两个都比较简单。
这里只对CVE-2018-1305进行简要分析。
Java EE提供了类似ACL权限检查的注解,可以直接用于修饰Java Servlet,用于对Servlet进行ACL保护。
现假设有两个Servlet:
Servlet1,访问路径为/ servlet1 / *
Servlet2,访问路径为/ servlet1 / servlet2 / *
Servlet1上有如下图的Security Constraint(简单理解就是ACL):
Servlet2上并没有ACL。
然而因为Servlet2的访问URL位于Servlet1的下一级(/ servlet1 / servlet2是/ servlet1 /的“子目录”),所以Tomcat中正常的代码逻辑应该是,虽然Servlet2上面没有ACL,但是Servlet2应该继承Servlet1的ACL。
正常情况应该是:
先访问/ servlet1,返回403,因为请求被ACL拦截了
再访问/ servlet1 / servlet2,返回403,因为请求被ACL拦截
那么实际的问题在哪里?
Tomcat在接收到Servlet访问请求后,在实例化Servlet对象之前,会先扫描被访问的Servlet上注册的ACL。如果存在ACL,则将ACL规则添加到一个Context唯一的列表中。随后再检查当前访问的Servlet是否被ACL保护。
ACL扫描org.apache.catalina.authenticator.AuthenticatorBase#invoke:
ACL检查org.apache.catalina.authenticator.AuthenticatorBase#invoke:
问题出在,如果在Servlet1(/ servlet1)被访问之前,有人先访问了Servlet2(/ servlet1 / servlet2)。流程如下:
Tomcat接收到Servlet2的访问请求
Tomcat扫描Servlet2上注册的ACL,发现Servlet2上没有注册ACL
Tomcat检查Servlet2是否被ACL保护。这一步,因为Servlet2在Servlet1之前被访问,所以导致Servlet1上注册的ACL规则还没有被Tomcat发现。所以,原本应该被Servlet1的ACL规则保护的Servlet2,就处在了未受保护的状态。
访问http:// localhost:8080 / CVE-2018-1305 / servlet1 / servlet2,此时servlet1的ACL没被Tomcat加载,所以访问成功
访问http:// localhost:8080 / CVE-2018-1305 / servlet1,被拒绝访问了,此时Tomcat加载了servlet1的ACL
再访问http:// localhost:8080 / CVE-2018-1305 / servlet1 / servlet2,被拒绝访问了,因为Tomcat已经加载了servlet1的ACL
Tomcat的修复了ACL注册的方式。以前是采用,在Servlet中真正被访问之前才去注册此Servlet上的ACL。现在改成了,在上下文启动的时候,就去扫描该上下文所有的Servlet上注册的ACL,并添加到acl列表中。
在任何一个上下文启动时,Tomcat都会自动调用:
org.apache.catalina.startup.WebAnnotationSet#loadApplicationServletAnnotations
而其中,添加了如下ACL相关代码:
只有当你使用的Tomcat处于受影响的Tomcat版本中,而且你的应用依赖于Java EE Constraints来进行ACL保护的时候,才受影响。
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.