[备份]CVE-2020-1957分析

简介

Apache Shiro是一个安全框架,在Java开发中使用非常广,可以很方便地做权限管理。一个权限绕过漏洞,危害不是很大,因为一般情况下绕过Shiro还有具体的操作权限验证,很少发生绕过Shiro获取很大权限这种事。最有名的Shiro反序列化漏洞打算后续分析

 

漏洞复现

下载官方示例:https://github.com/lenve/javaboy-code-samples

使用其中的shiro/shiro-basic项目,修改org\javaboy\shirobasic\ShiroConfig.java代码,修改配置,设置登录url为/login,设置成功后跳转的url是/index,设置登录失败的url为/unauthorizedurl,对于/admin下的所有路径都进行权限验证

添加一个路由,在org\javaboy\shirobasic\LoginController.java中增加如下代码

启动项目,访问/index,没有被拦截 img

访问/admin/index,不允许访问,跳到登录页 img

输入http://localhost:8080/xxx/..;/admin/index成功绕过 img

漏洞分析

从大体上理解,其实让Shiro和SpringBoot获取到的URL不同,就可以做到绕过

从shiro获取uri的入口分析:org\apache\shiro\web\util\WebUtils.java,可以看到,通过getRequestUri函数获得的uri并不是真正的

img

跟入getRequestUri函数,可以看到在return normalize(decodeAndCleanUriString(request, uri));之前,uri还是正确的

img

重点来看normalizedecodeAndCleanUriString方法。不难看出,decodeAndCleanUriString方法进行了字符串截断,最后得到的uri是/xxx/..

其中normalize方法并没有什么特殊的地方,一个标准库,替换反斜杠,去除双斜杠,处理/..//./等特殊情况,而获取到的uri会在org\apache\shiro\web\filter\mgt\PathMatchingFilterChainResolver.java类的getChain方法做校验,而/xxx/..并不会匹配到/admin/**

到这里就绕过了Shiro,但还要让SpringBoot解析成对应的URL漏洞才会生效。找到SpringBoot解析URL的类org\springframework\web\util\UrlPathHelper.javagetPathWithinServletMapping方法,断点调试后发现返回的是/admin/index,成功触发漏洞。HttpServletRequest.getServletPath()是标准方法,并不存在漏洞,所以本质上还是shiro的校验问题

img

补丁分析

官方补丁:https://github.com/apache/shiro/commit/3708d7907016bf2fa12691dff6ff0def1249b8ce

以上文的payload/xxx/...;/admin/index,这里uri会变成//admin/index