Shiro鉴权绕过

环境搭建

了解Ant 风格路径表达式
https://blog.csdn.net/sinat_18619901/article/details/95931601

CVE-2020-11989

影响条件

Apache Shiro < 1.5.3
Spring 框架中只使用 Shiro 鉴权

代码分析

首先在com.shiro.vuln.Shiro.ShiroConfig#shiroFilterFactoryBean中添加如下内容

1
map.put("/admin/*","authc");

然后在com.shiro.vuln.Controller.UserController添加路由

1
2
3
4
5
@ResponseBody
@GetMapping("/admin/{name}")
public String namePage(@PathVariable String name){
return "Hello" + name;
}

payload

1
http://127.0.0.1:8080/admin/a%252Fb

正常情况下访问/admin/xxx 或 /admin/xxx/xxx 分别会跳转302和404,但是上面那样访问可以直接绕过权限校验并且返回我们想要访问的控制器;下面来分析下可以绕过的原因,首先在org.apache.shiro.web.util.WebUtils#getPathWithinApplication位置下断点,然后使用payload访问

首先会经过String requestUri = getRequestUri(request); 跟进该方法

首先会进入到if条件中,对传入的路径进行一次URL解码,此时uri的值为//admin/a%2Fb
然后会运行到
return normalize(decodeAndCleanUriString(request, uri));
还会对uri进行一次URL解码,此时return的值为/admin/a/b 也就是requestUri的值为/admin/a/b 然后一路向下运行,来到org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain

该方法中会使用到org.apache.shiro.util.AntPathMatcher#doMatch 来对uri和我们设置的鉴权规则进行匹配,目前的uri是/admin/a/b 而我们设置的规则为/admin/* 这样的规则是匹配不到目前的uri的所以shiro会认为此处没有权限问题,会直接放过;接着看下spring中对URL的处理,在org.springframework.web.util.UrlPathHelper#getLookupPathForRequest中下断

可以看到spring对url只进行了一次URL解码,这样可以匹配到我们自己添加的控制器,完成访问

CVE-2020-13933

影响条件

Apache Shiro < 1.6.0
Spring 框架中只使用 Shiro 鉴权

代码分析

测试环境同CVE-2020-11989一样,在maven中将shiro版本改为1.5.3

payload

1
http://127.0.0.1:8080/admin/%3Babc

在org.apache.shiro.web.util.WebUtils#getPathWithinApplication中下断

首先会取请求路径进行一次URL解码,然后进入到removeSemicolon方法,如图

该方法会移除路径中的;及其后面的内容,然后返回剩下的部分,本例中返回的就是/admin/ 接着代码就会运行到鉴权流程,对/admin/进行鉴权,由于设置的权限校验规则为/admin/* ,这是匹配不到/admin/的,所以就达到了权限的绕过。

CVE-2020-17523

影响条件

Apache Shiro < 1.7.1
Spring 框架中只使用 Shiro 鉴权

代码分析

测试环境同CVE-2020-11989一样,在maven中将shiro版本改为1.7.0

payload

1
http://127.0.0.1:8080/admin/%20

问题主要在于在将待校验路径分割为数组的过程中,使用了trim函数来消除空格;我们在org.apache.shiro.util.AntPathMatcher#doMatch 方法中下断点

跟进StringUtils.tokenizeToStringArray(path, this.pathSeparator); 此时path 的值为 /admin/ (带空格),

接着跟入到org.apache.shiro.util.StringUtils#tokenizeToStringArray(java.lang.String, java.lang.String, boolean, boolean)

该方法中会对传进来的元素执行trim函数,当路径中的空格经过该方法时会被去除,那么鉴权时检测的路径就会变成/admin/(无空格),很明显在鉴权时会匹配不到该路径,也就绕过了shiro的权限检测。

记录

在CVE-2020-13933中,当测试/admin/;abc 这样的payload时,会发现如下情况

这里其实是spring处理的问题,下断到org.springframework.web.util.UrlPathHelper#getLookupPathForRequest

跟进this.getPathWithinServletMapping(request);

继续跟进String requestUri = this.getRequestUri(request);

然后进入org.springframework.web.util.UrlPathHelper#decodeAndCleanUriString

会发现他会先移除;及其后面的部分,然后在进行url解码,所以如果我们直接访问/admin/;abc的话,spring处理后会直接变成/admin/,也就访问不到控制器了