Java Shiro 權限繞過


前言

1、這篇作為Shiro的權限繞過的筆記

2、這篇文章作為之前筆記Filter權限繞過筆記的拓展

Filter權限繞過筆記:https://www.cnblogs.com/zpchcbd/p/14815501.html

3、謝謝酒館師傅發個一個文章 shiro權限繞過史,方便學習

本片筆記參考文章:

文章一:https://www.anquanke.com/post/id/240033
文章二:https://blog.riskivy.com/shiro-權限繞過漏洞分析(cve-2020-1957)/
文章三:Shiro權限繞過史,作者也不知道誰,就一個pdf

什么是Shiro

Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼和會話管理。使用Shiro的易於理解的API,您可以快速、輕松地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。

關於Shiro漏洞歷史線

CVE-2020-17523(權限繞過)
Apache Shiro before 1.7.1, when using Apache Shiro with Spring, a specially crafted HTTP request may cause an authentication bypass.

CVE-2020-17510(權限繞過)
Apache Shiro before 1.7.0, when using Apache Shiro with Spring, a specially crafted HTTP request may cause an authentication bypass.

If you are NOT using Shiro’s Spring Boot Starter (shiro-spring-boot-web-starter), you must configure add the ShiroRequestMappingConfig auto configuration to your application or configure the equivalent manually.

CVE-2020-13933(權限繞過)
Apache Shiro before 1.6.0, when using Apache Shiro, a specially crafted HTTP request may cause an authentication bypass.

CVE-2020-11989(權限繞過)
Apache Shiro before 1.5.3, when using Apache Shiro with Spring dynamic controllers, a specially crafted request may cause an authentication bypass.

CVE-2020-1957(權限繞過)
Apache Shiro before 1.5.2, when using Apache Shiro with Spring dynamic controllers, a specially crafted request may cause an authentication bypass.

CVE-2019-12422(shiro-721)
Apache Shiro before 1.4.2, when using the default “remember me” configuration, cookies could be susceptible to a padding attack.

CVE-2016-6802(權限繞過)
Apache Shiro before 1.3.2 allows attackers to bypass intended servlet filters and gain access by leveraging use of a non-root servlet context path.

CVE-2016-4437(shiro-550)
Apache Shiro before 1.2.5, when a cipher key has not been configured for the “remember me” feature, allows remote attackers to execute arbitrary code or bypass intended access restrictions via an unspecified request parameter.

參考文章:https://shiro.apache.org/security-reports.html

環境搭建

第一步

第二步

第三步:

第四步:

maven添加依賴

        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.2</version>
        </dependency>

前置知識點

問題:

1、在tomcat和shiro的filter中,哪個會先進行執行?后進行執行?

2、關於Shiro攔截器

Shiro框架通過攔截器功能來實現對用戶訪問權限的控制和攔截。

Shiro中常見的攔截器有anon,authc等攔截器,還有其他的,這里是探討關於authc攔截器的繞過。

1.anon為匿名攔截器,不需要登錄就能訪問,一般用於靜態資源,或者移動端接口
2.authc為登錄攔截器,需要登錄認證才能訪問的資源。
...

3、關於shiro的攔截匹配模式

Shiro的URL路徑表達式為Ant格式:

/hello:只匹配url,比如 http://demo.com/hello
/h?:只匹配url,比如 http://demo.com/h+任意一個字符
/hello/*:匹配url下,比如 http://demo.com/hello/xxxx 的任意內容,不匹配多個路徑
/hello/**:匹配url下,比如 http://demo.com/hello/xxxx/aaaa 的任意內容,匹配多個路徑

4、shiro是如何運行的?

我這里也不太懂shiro,這里就正常的看下shiro源碼是如何運行的就可以了,簡單的學下

shiroConfig需要通過ShiroFilterFactoryBean類來進行配置,一個正常的ShiroConfig.java如下所示

@Configuration
public class ShiroConfig {
    @Bean
    MyRealm myRealm(){
        return new MyRealm();
    }

    @Bean
    public DefaultWebSecurityManager manager(){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(myRealm());
        return manager;
    }

    @Bean
    public ShiroFilterFactoryBean filterFactoryBean(){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(manager());
        factoryBean.setUnauthorizedUrl("/login");
        factoryBean.setLoginUrl("/login");
        Map<String, String> map = new HashMap<>();
        map.put("/login", "anon");
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }
}

對於路徑的訪問權限的控制都是基於ShiroFilterFactoryBean類來進行配置的

    @Bean
    public ShiroFilterFactoryBean filterFactoryBean(){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(manager());
        factoryBean.setUnauthorizedUrl("/login");
        factoryBean.setLoginUrl("/login");
        Map<String, String> map = new HashMap<>();
        map.put("/login", "anon");
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }

這里可以來到ShiroFilterFactoryBean類中,看它是如何作用的,該類中存在一個getObject方法

    public Object getObject() throws Exception {
        if (instance == null) {
            instance = createInstance();
        }
        return instance;
    }

其中createInstance方法是來創建相關Shiro Filter,結果是返回一個繼承了AbstractShiroFilter的SpringShiroFilter對象

    protected AbstractShiroFilter createInstance() throws Exception {

        log.debug("Creating Shiro Filter instance."); // 創建shiro Filter的實例

        SecurityManager securityManager = getSecurityManager();
        if (securityManager == null) {
            String msg = "SecurityManager property must be set.";
            throw new BeanInitializationException(msg);
        }

        if (!(securityManager instanceof WebSecurityManager)) {
            String msg = "The security manager does not implement the WebSecurityManager interface.";
            throw new BeanInitializationException(msg);
        }

        FilterChainManager manager = createFilterChainManager();

        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
        chainResolver.setFilterChainManager(manager);

        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
    }

SpringShiroFilter這個對象是繼承了AbstractShiroFilter,而這個AbstractShiroFilter中存在一個doFilterInternal,這個方法我自己有了解,因為Filter的內存文章中tomcat這個其中的InternaldoFilter就是去調用我們每個Filter對象中實現的doFilter方法的一個方法,而這里的doFilterInternal可能不太一樣,它是通過executeChain來進行鏈式調用傳入的chain參數,這個chain是一個FilterChain對象

其中executeChain方法來對傳入的FilterChain對象進行處理調用doFilter方法

此時前面的tomcat的Filter對象中的doFilter已經走完了,tomcat的走完了才開始走shiro的filter(PS:此時tomcat的過濾器並不是完全走完,還有最后一個在shiro的后面)

接着就是getExecutionChain方法,其中就會通過FilterChainResolver的getChain方法來進行解析,從這里開始shiro的攔截器就開始進行發揮作用了,這里如果是被正確的攔截了,那么原始的chain則會被替換為shiro的filterChainManager.proxy(originalChain, pathPattern)所返回的FilterChain,如果沒有被攔截則最后不會被替換,還是走原來的chain

那么shiro是如何判斷是否被攔截的?可以繼續看

繼續跟到pathMatches方法中去看,他會用自己的一個路徑匹配器PathMatcher來進行比較

最后doMatch方法獲取 需要校驗的路徑 和 當前客戶端訪問的路徑來進行比較,是否是需要進行攔截的

判斷是否需要攔截,具體根據其中的matchStrings方法來進行判別,到這里一次請求的判斷就結束了

接下來看漏洞分析...

CVE-2016-6802(SHIRO-682)

參考:https://issues.apache.org/jira/browse/SHIRO-682

影響版本: shiro<1.5.0

漏洞原理:shiro與spring的URI中末尾的/不同導致的權限繞過

其中表示匹配零個或多個字符串,/可以匹配/hello,但匹配不到/hello/因為*通配符無法匹配路徑。

假設/hello接口設置了authc攔截器,訪問/hello將會被進行權限判斷,如果請求的URI為/hello/呢,/*的URL路徑表達式將無法正確匹配,放行。然后進入到spring(Servlet)攔截器,而spring中 /hello 形式和 /hello/形式的URL訪問的資源是一樣的,從而導致了繞過。

漏洞分析:

這里的話從getChain方法開始看,這里會先獲取相關的URI,然后傳入pathMatches來進行比較

我們設置一個權限攔截器,如下所示:

    @Bean
    public ShiroFilterFactoryBean filterFactoryBean(){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(manager());
        factoryBean.setUnauthorizedUrl("/login");
        factoryBean.setLoginUrl("/login");
        Map<String, String> map = new HashMap<>();
        map.put("/admin", "authc"); // 新增的攔截器
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }

訪問:http://127.0.0.1:8080/admin/

首先來到的地方還是getChain

跟到doMatches 這里調用的是doMatch,這里/admin//admin經過tokenizeToStringArray返回的數據是一樣的

/admin//admin經過tokenizeToStringArray返回的數據是一樣的,但是接着后面就是會進行判斷,如果結尾存在/,則返回為False

返回為False,就不會走shiro的攔截器了,最后就成功繞過了,shiro的過濾器攔截

而正常的訪問:http://127.0.0.1:8080/admin ,則會被shiro的攔截器捕獲

問題思考

在CVE-2016-6802(SHIRO-682)中,通過后面加/,來繞過了shiro的攔截器,那么此時的URI則是http://127.0.0.1:8080/admin/,那么又為什么可以訪問到接口為admin接口的資源呢?

這里就要引出sprng的路徑處理的過程了...

接着來看spring是如何處理URI的,此時我們已經到了如下的位置

F8走出來,到此shiro的過濾攔截器已經執行完成了,又開始進行轉發請求的操作chain.doFilter(request, response)

到這里可以繼續看下過濾器的數量,shiro過濾器走的是filterFactoryBean,那么此時還有最后一個過濾器還沒走,Tomcat WebSocket (JSR356) Filter

走完最后一個Tomcat Filter之后,請求被轉發到了spring中,這里的話,斷在org/springframework/web/util/UrlPathHelper.java#getLookupPathForRequest方法上,此時在Shiro包裝的HttpServlet來進行處理,這里則返回了/admin/

接着F8一直走到lookupHandlerMethod,來調用對應接口的方法,這個地方就是重點,看他如何處理這個/admin/,這里就不跟了,可以自己跟下,調用鏈如下,我的springboot版本2.5.2

getMatchingPattern:336, PatternsRequestCondition (org.springframework.web.servlet.mvc.condition)
getMatchingPatterns:296, PatternsRequestCondition (org.springframework.web.servlet.mvc.condition)
getMatchingCondition:281, PatternsRequestCondition (org.springframework.web.servlet.mvc.condition)
getMatchingCondition:406, RequestMappingInfo (org.springframework.web.servlet.mvc.method)
getMatchingMapping:109, RequestMappingInfoHandlerMapping (org.springframework.web.servlet.mvc.method)
getMatchingMapping:67, RequestMappingInfoHandlerMapping (org.springframework.web.servlet.mvc.method)
addMatchingMappings:442, AbstractHandlerMethodMapping (org.springframework.web.servlet.handler)
lookupHandlerMethod:402, AbstractHandlerMethodMapping (org.springframework.web.servlet.handler)

官方修復方法:

1.5.0版本修復源自tomsun28提交的PR代碼,代碼修復位置為pathsMatch:125, PathMatchingFilter (org.apache.shiro.web.filter),該修復方式是通過判斷requestURI是否以/為結尾,如果以/結尾的話,則去掉尾部的/符號在與URL表達式進行比較。

也就是當requestURI為/hello/1/等以/為結尾的URI的時候,都會被清除最后的/號,再進行URL路徑匹配。

可能自己會試下訪問:http://127.0.0.1:8080/admin//

但是在request.getRequestURI函數即是在后面多個/的時候,獲取到的結尾還是一個/,接着又被取length-1,那么這里就沒辦法了。

CVE-2020-1957

影響版本: shiro<1.5.2

漏洞原理:shiro與spring的URI中對;處理不同,導致繞過

類型: 權限繞過

因為上面大致將整個shiro的流程都講了一遍了,現在主要分析的就是漏洞本身了!

介紹:CVE-2020-1957則是對CVE-2016-6802的繞過

按照原來的繞過,如下圖所示,發現已經無法進行繞過了

繞過方法:分號;

分析

shiro的部分

spring的部分

可以看下getPathWithinApplication方法是如何處理的,因為我們這里沒有設置ContextPath,所以默認為空

接着跟進getRequestUri方法中

decodeAndCleanUriString方法中

decodeAndCleanUriString方法中又調用了removeSemicolonContent,removeSemicolonContent方法中有調用了removeSemicolonContentInternal,結果返回如下

接着又是decodeRequestString,這里就是簡單的URL解碼,沒有影響,那么這里思考下,那么我們一次的訪問就是二次解碼,這個點能不能在其他地方上進行利用?我也不太清楚

接着就是getSanitizedPath方法

這個方法的作用則是將//轉化為/,那么此時就是將//admin/cmd轉化為/admin/cmd

最后返回就是為/admin/cmd,一個正常的訪問路徑,最后進行調用從而繞過

稍微總結下:

這次的繞過其實還是shiro和spring的路徑處理方式不同,shiro是如何處理的?

比如http://127.0.0.1:8080/;/admin,shiro則是認為是訪問http://127.0.0.1:8080/

spring是如何處理的?

比如http://127.0.0.1:8080/;/admin,shiro則是認位是訪問http://127.0.0.1:8080/admin

這就造成了與Shiro處理⽅式的差異,Shiro是直接截斷后⾯所有部分,⽽Spring只會截斷【分號之后,斜杠之前】的部分

官方修復方案

shiro中的getRequestUri修改為如下:

    public static String getRequestUri(HttpServletRequest request) {
        String uri = (String) request.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE);
        if (uri == null) {
            uri = valueOrEmpty(request.getContextPath()) + "/" +
                  valueOrEmpty(request.getServletPath()) +
                  valueOrEmpty(request.getPathInfo());
        }
        return normalize(decodeAndCleanUriString(request, uri));
    }

    private static String valueOrEmpty(String input) {
        if (input == null) {
            return "";
        }
        return input;
    }

重新調試下,發現在shiro攔截器處理之前就進行了處理,如下

具體修改如下,在自定義的getRequestUri方法中用ContextPathServletPathPathInfo三者拼接的⽅式獲取路由,由於 ServletPath 能夠正確的處理分號,通過這種⽅式來獲取對應的路由能夠成功修復此漏洞。

    public static String getRequestUri(HttpServletRequest request) {
        String uri = (String) request.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE);
        if (uri == null) {
            uri = valueOrEmpty(request.getContextPath()) + "/" +
                  valueOrEmpty(request.getServletPath()) +
                  valueOrEmpty(request.getPathInfo());
        }
        return normalize(decodeAndCleanUriString(request, uri));
    }

    private static String valueOrEmpty(String input) {
        if (input == null) {
            return "";
        }
        return input;
    }

CVE-2020-11989

影響版本: shiro<1.5.3

環境配置

1、shiro的版本

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.2</version>
        </dependency>
    </dependencies>

2、設置下context-path

在資源文件的application.properties文件中進行設置

server.servlet.context-path=/test

3、在多添加一個admin路徑下的一個接口

TestController.java

    @ResponseBody
    @RequestMapping(value="/admin/cmd", method = RequestMethod.GET)
    public String cmd(){
        return "execute command endpoint!";
    }

    @ResponseBody
    @RequestMapping(value="/admin", method = RequestMethod.GET)
    public String admin(){
        return "secret key: admin888!";
    }

ShiroConfig.java

    @Bean
    public ShiroFilterFactoryBean filterFactoryBean(){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(manager());
        factoryBean.setUnauthorizedUrl("/login");
        factoryBean.setLoginUrl("/login");
        Map<String, String> map = new HashMap<>();
        map.put("/login", "anon");
        map.put("/admin", "authc");
        map.put("/admin/*", "authc");
        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }

漏洞復現

根據漏洞payload訪問:http://127.0.0.1:8080/test;/admin/cmd,但是發現沒有進行繞過成功,而是報錯了

接着查了相關的文章,我這里繼續把spring-boot的版本進行替換

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

再次訪問http://127.0.0.1:8080/test;/admin/cmd,這里卻發現了成功繞過

接着我在2.2.6的基礎上,將context-path去掉,繼續訪問``http://127.0.0.1:8080/test;/admin/cmd`,這里發現又不行了

問題

1、為什么需要設置context-path,權限才能繞過?

2、為什么2.5.2的spring-boot版本不可以進行利用,卻在2.2.6的版本上可以進行利用?

問題1

1、為什么需要設置context-path,權限才能繞過?

回想下對於shiro的1.5.2的漏洞代碼修復,官方變動的地方為getRequestURI的方式,那么產生這個問題的肯定也是來自這里,所以這里仔細來分析這個地方,這里調試的環境為2.2.6

其實想下,它的修復方式就是通過如下來獲取getRequestURI來進行獲取請求路徑,也就是如下代碼,可以看到它是通過 ContextPath + ServletPath + getPathInfo 來進行拼接而成的

    public static String getRequestUri(HttpServletRequest request) {
        String uri = (String) request.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE);
        if (uri == null) {
            uri = valueOrEmpty(request.getContextPath()) + "/" +
                  valueOrEmpty(request.getServletPath()) +
                  valueOrEmpty(request.getPathInfo());
        }
        return normalize(decodeAndCleanUriString(request, uri));
    }

當沒有ContextPath設定的時候,我們訪問http://127.0.0.1:8080/admin;/cmd,那么此時getRequestURI處理過后就是//admin/cmd,那么這個則會被shiro過濾器所攔截

上面的圖中其實還沒走decodeAndCleanUriString方法,這個方法走了之后//admin/cmd,也就會成為/admin/cmd

但是如果ContextPath有設定的時候,我們再來訪問http://127.0.0.1:8080/test;/admin/cmd,注意的是我們這里設定的ContextPath為test,所以才這么訪問,可以看到此時getRequestURI處理過后則是/test;//admin/cmd

那么繼續走decodeAndCleanUriString方法,這里最后就拿到了一個/test

這里你就會發現獲取ContextPath方法和getServletPath、getPathInfo方法不同的就是,它不會對;這個進行處理,導致decodeAndCleanUriString的時候將;后面的都去除掉,最后只剩下了一個/test

然后這里的/test,最后的結果就是在shiro過濾器中沒有匹配到。

接着看spring中是如何運作的?

還是老樣子,打斷點在org/springframework/web/util/UrlPathHelper.java#getLookupPathForRequest方法中,可以看到這里分析的2.2.6

2.2.6默認走的就是getPathWithinServletMapping方法,這個方法返回的則是/admin/cmd

最后就是通過解析對應的controller的方法,獲得對應的handler來進行反射調用

其實自己總結下:這個CVE的產生則是跟shiro和spring對ContextPath的處理方式不同產生的權限繞過,所以也就是這個漏洞為什么需要ContextPath的支持。

2、為什么2.5.2的SpringBoot版本不可以進行利用,卻在2.2.6的版本上可以進行利用

繼續走第二個問題,這里把SpringBoot的環境換成2.5.2進行調試

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

繼續之前的過程,先看shiro過濾器這邊的繞過,可以繞過,如下所示,獲得是/test

接着看spring的路由走法,可以發現跟2.2.6的走法是不同的,主要受到了alwaysUseFullPath參數值的影響

alwaysUseFullPath為true和false的區別到底是怎么樣的呢?

可以看到如果為true的話,下面的語句不會執行方法getPathWithinServletMapping了,而是直接返回一個getPathWithinApplication處理過后的結果,而單單只經過getPathWithinApplication方法處理的最后在調用對應方法的時候就調用不到

alwaysUseFullPath為true的時候結果為如下

alwaysUseFullPath為false的時候結果為如下

當Spring Boot版本在小於等於2.3.0.RELEASE的情況下,alwaysUseFullPath為默認值false,這會使得其獲取ServletPath,所以在路由匹配時相當於會進行路徑標准化包括對%2e解碼以及處理跨目錄,這可能導致身份驗證繞過。而反過來由於高版本將alwaysUseFullPath自動配置成了true從而開啟全路徑,又可能導致一些安全問題。

官方修復方案

該漏洞是Shiro與Servlet對於ContextPath處理的差異,Shiro將ContextPath與其他路徑拼接后代入了格式化方法進⾏處理,而該方法將分號后的所有部分都截斷,這是漏洞的核心。

https://github.com/apache/shiro/compare/shiro-root-1.5.2...shiro-root-1.5.3

重新跟下,它是如何修復的?

訪問http://127.0.0.1:8080/test;/admin/cmd

如下可以看到,這里的話在shiro處理路徑的時候,getPathWithinApplication方法出來之后就是/admin/cmd,這里並不是將;后面的內容都去掉了

可以看下getPathWithinApplication比起上個版本是如何修復的?

不對Servletpath進行處理了,這里處理的只有getServletPath(request) + getPathInfo(request)

最后匹配了規則之后,走的就是shiro過濾器的地方

CVE-2020-13933

影響版本: shiro<1.6.0

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.3</version>
        </dependency>

環境配置

    @ResponseBody
    @RequestMapping(value="/hello/{index}", method= RequestMethod.GET)
    public String hello1(@PathVariable String index){
        // CVE-2020-13933
        return "Hello World "+ index.toString() + "!";
    }

    @Bean
    public ShiroFilterFactoryBean filterFactoryBean(){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(manager());
        factoryBean.setUnauthorizedUrl("/login");
        factoryBean.setLoginUrl("/login");
        Map<String, String> filterMap = new HashMap<>();
        filterMap.put("/login", "anon");
//        filterMap.put("/admin/*", "authc");
        filterMap.put("/hello/*", "authc");
//        filterMap.put("/admin", "authc");
//        map.put("/static/**", "anon");
        //map.put("/**", "authc");
        factoryBean.setFilterChainDefinitionMap(filterMap);
        return factoryBean;
    }

shiro分析

getServletPath():默認會將URI進⾏Urldecode

接着就是下面pathMatches方法進行相關匹配的shiro攔截器進行比較

不滿足,*** 不等,所以返回false,從而進行繞過

需要注意的是:

如果這兩個都存在的話,那么對於訪問http://127.0.0.1:8080/hello/%3b111,這種就無法繞過

filterMap.put("/hello/*", "authc");
filterMap.put("/hello","authc");

原因在於shiro的判斷中pathMatches的方法的行為。

spring分析

getPathWithinServletMapping方法

得到的路徑為/hello/;1

漏洞點出在Shiro會先進⾏urldecode后再進⾏分號截斷,⽽Spring⾸先進⾏了分號截斷,隨后才會進⾏urldecode。正是兩者之間微⼩的差異才導致了漏洞的產⽣。

官方修復

https://github.com/apache/shiro/compare/shiro-root-1.5.3...shiro-root-1.6.0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM