漏洞信息
Shiro 权限绕过漏洞:shiro框架通过拦截器功能来对用户访问权限进行控制,如anon,authc’等拦截器。Spring web在匹配url的时候校验未完全,造成绕过,访问未授权路径
shiro
Apache Shiro是一个java安全框架。可以进行身份验证、授权、密码和会话管理。
三个核心组件:Subject、SecurityManager、Realms
漏洞分析
内容来自spoock,网址https://blog.spoock.com/2020/05/09/cve-2020-1957/
在URL在项目中传递,首先传入URL1,经过shiro权限检验URL2,最后到springboot项目找到路由来处理URL3
漏洞的出现就在URL1,URL2和URL3 有可能不是同一个URL,这就导致我们能绕过shiro的校验,直接访问后端需要首选的URL。本例中的漏洞就是因为这个原因产生的。
这里URL还是传入的原始URL:/xxxx/…;/admin/index
接着程序会用decodeAndCleanUriString(), 进行处理:
decodeAndCleanUriString 以 ;
截断后面的请求,所以此时返回的就是 /xxxx/..
.然后程序调用normalize() 对decodeAndCleanUriString()处理得到的路径进行标准化处理. 标准话的处理包括:
- 替换反斜线
- 替换
//
为/
- 替换
/./
为/
- 替换
/../
为/
经过经过getPathWithinApplication()函数的处理,最终shiro 需要校验的URL 就是 /xxxx/..
. 最终会进入到 org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver 中的 getChain()方法会URL校验. 关键的校验方法如下
最终我们的原始请求 /xxxx/..;/admin/index
就会进入到 springboot中. springboot对于每一个进入的request请求也会有自己的处理方式,找到自己所对应的mapping. 具体的匹配方式是在:org.springframework.web.util.UrlPathHelper 中的 getPathWithinServletMapping()
getPathWithinServletMapping() 在一般情况下返回的就是 servletPath, 所以本例中返回的就是 /admin/index.最终到了/admin/index 对应的requestMapping, 如此就成功地访问了后台请求.
由于 /xxxx/..
并不会匹配到 /admin/**
, 所以shiro权限校验就会通过
- 客户端请求URL:/xxxx/…;/admin/index
- shrio内部处理得到校验URL为/xxxx/…,校验通过
- springboot处理/xxxx/…;/admin/index,最终请求/admin/index,成功访问了后台请求
漏洞复现
使用vulhub进行搭建,下载地址:https://github.com/vulhub/vulhub,进入的CVE-2020-1957目录中,直接启动docker容器。
dockers-compose up -d
当显示done的时候,表示容器已经启动。可以在浏览器中访问了。
http://192.168.1.134:8080
使用burp进行抓包,在点击到Accout info时返回了一个响应码302的包,路径为/admin。
(响应码302:redirect,代表暂时性转移。将服务端的拦截器或者其他代码处理会被重定向到网址b。)
这里应该就是漏洞的所在了。尝试使用命令*/xxx/…;/admin/*,成功返回响应码200,绕过登录界面,成功进入后台。
在登陆界面是没有返回302的响应包的,只有一个平常的login,直接尝试修改。/xxx/…;/admin/
同样成功进入后台。
总结
该漏洞以特殊形式绕过了两次检测,携带恶意代码最终执行。当进行绕过时应该注重程序的检测方法,针对不同的方法进行绕过。
该漏洞重点是截断了检测,未对后半段url进行检测,中间没看出来为什么*;没啦。应该是使用程序中使用了decodeAndCleanUriString*类的函数对URL进行格式化处理。然后getPathWithinApplication匹配出了地址,/admin/index
传入servletPath。绕过成功。