Apache Shiro的CVE-2020-11989修补补丁依旧存在缺陷,由于shiro和spring在处理url中仍然存在差别,通过构造特殊的HTTP请求,可以再次绕过授权,访问未授权的信息。
影响范围
Apache Shiro < 1.6.0
Spring 框架中只使用 Shiro 鉴权
漏洞复现
配置如下
@Bean ShiroFilterFactoryBean shiroFilterFactoryBean(){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(securityManager()); bean.setLoginUrl("/login"); bean.setSuccessUrl("/index"); bean.setUnauthorizedUrl("/unauthorizedurl"); Map<String, String> map = new LinkedHashMap<>(); map.put("/doLogin/", "anon"); map.put("/admin/*", "authc"); bean.setFilterChainDefinitionMap(map); return bean; }
@GetMapping("/admin/{name}") public String admin(@PathVariable String name) { return "admin page"; } @GetMapping("/login") public String login() { return "please login!"; }
此漏洞关键还是在于shiro对URI的处理与Spring对URI处理的不同。
下面进行调试分析:
shiro处理URI如下所示:
经过对URI进行解码再去除分号,所以我们传入一个带编码的URI可以得到如下结果:
此处因为/admin/没有匹配到具体资源路径,所以通过过滤器到达Spring的处理逻辑。
而Spring的处理逻辑如下:
往下调试,这里得到的URI为解码前的原始URI:
之后在decodeAndCleanUriString方法里对URI进行相关处理。
注意这里Spring的处理逻辑为先去判断URI中是否存在分号,因为是编码过后的URI,所以未能直接识别出分号,所以index为-1,所以未进入if分支,从而仍然返回输入的带编码的URI。
接下来再进行对URI的解码。得到URI如下图:
之后进行匹配从而获取相应资源。
漏洞修复
添加一个一个InvalidRequestFilter类,该类从全局上对分号,反斜杠和非ASCII字符进行了过滤。(他急了他急了)