shiro 權(quán)限繞過漏洞 CVE-2020-11989

0x00 漏洞復現(xiàn)

pom.xml

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

application.properties

server.context-path=/test

ShiroConfig

@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<String, String>();
        map.put("/hello/*", "authc");
        //map.put("/hello/**", "authc"); //in version 1.7.0 will not trigger CVE-2020-17523
        bean.setFilterChainDefinitionMap(map);
        return bean;
    }

spring

    @RequestMapping("/hello/{name}")
    public String hello2(@PathVariable String name) {
        return "auth hello/{_" + name + "_}, there ";
    }

觸發(fā)權(quán)限繞過的訪問請求如下:
http://127.0.0.1:8080/test/hello/a%252fa
response如下:auth hello/{a%2fa}, there
正常的訪問請求如下:
http://127.0.0.1:8080/test/hello/aa
response如下:跳轉(zhuǎn)到登錄頁面。

"/"的URL編碼為"%2f",在瀏覽器中"%"二次編碼為"%252f"伦忠。
觸發(fā)此漏洞的根源在于shiro在進行filter匹配的過程中背伴,對url進行了兩次解碼梭姓;而在spring的框架中,并未進行兩次URL解碼哈雏。因此兩者造成了不一致。

0x01 源碼分析

PathMatchingFilterChainResolver.java文件中的getchain函數(shù)中如下調(diào)用,獲取requestURI贩疙,導致requestURI被解析為"/hello/a/a"讹弯,而無法與pattern"/hello/*"匹配上。

String requestURI = getPathWithinApplication(request);

在WebUtils.java中getPathWithinApplication函數(shù)

public static String getPathWithinApplication(HttpServletRequest request) {
        String contextPath = getContextPath(request);
        String requestUri = getRequestUri(request);
        if (StringUtils.startsWithIgnoreCase(requestUri, contextPath)) {
            // Normal case: URI contains context path.
            String path = requestUri.substring(contextPath.length());
            return (StringUtils.hasText(path) ? path : "/");
        } else {
            // Special case: rather unusual.
            return requestUri;
        }
    }

getRequestUri函數(shù)

    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));
    }

decodeAndCleanUriString函數(shù)

    private static String decodeAndCleanUriString(HttpServletRequest request, String uri) {
        uri = decodeRequestString(request, uri);
        int semicolonIndex = uri.indexOf(';');
        return (semicolonIndex != -1 ? uri.substring(0, semicolonIndex) : uri);
    }

decodeRequestString函數(shù)

    public static String decodeRequestString(HttpServletRequest request, String source) {
        String enc = determineEncoding(request);
        try {
            return URLDecoder.decode(source, enc);
        } catch (UnsupportedEncodingException ex) {
            if (log.isWarnEnabled()) {
                log.warn("Could not decode request string [" + Encode.forHtml(source) + "] with encoding '" + Encode.forHtml(enc) +
                        "': falling back to platform default encoding; exception message: " + ex.getMessage());
            }
            return URLDecoder.decode(source);
        }
    }

因為采用ant風格的匹配这溅,所以组民,如果pattern配置為"/hello/**"則不會觸發(fā)此漏洞。

patch分析

diff
https://github.com/apache/shiro/compare/shiro-root-1.5.2...shiro-root-1.5.3
getPathWithinApplication函數(shù)進行了升級悲靴,不再調(diào)用會進行二次URL解碼的getRequestUri函數(shù)臭胜。

    public static String getPathWithinApplication(HttpServletRequest request) {
        return normalize(removeSemicolon(getServletPath(request) + getPathInfo(request)));
    }
    private static String getServletPath(HttpServletRequest request) {
        String servletPath = (String) request.getAttribute(INCLUDE_SERVLET_PATH_ATTRIBUTE);
        return servletPath != null ? servletPath : valueOrEmpty(request.getServletPath());
    }

    private static String getPathInfo(HttpServletRequest request) {
        String pathInfo = (String) request.getAttribute(INCLUDE_PATH_INFO_ATTRIBUTE);
        return pathInfo != null ? pathInfo : valueOrEmpty(request.getPathInfo());
    }

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

在shiro 1.5.3版本中,沒有地方再調(diào)用WebUtils.getRequestUri癞尚,該方法標識為已廢棄耸三。
那么廢棄了getRequestUri方法是否會觸發(fā)CVE-2020-1957呢?
答案是并不會浇揩,在getPathWithinApplication方法中并未直接獲取uri仪壮,而是通過getServletPath和getPathInfo分別獲取的。

References

https://xlab.tencent.com/cn/2020/06/30/xlab-20-002/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胳徽,一起剝皮案震驚了整個濱河市积锅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌养盗,老刑警劉巖缚陷,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異爪瓜,居然都是意外死亡蹬跃,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門铆铆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝶缀,“玉大人,你說我怎么就攤上這事薄货∥潭迹” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵谅猾,是天一觀的道長柄慰。 經(jīng)常有香客問我,道長税娜,這世上最難降的妖魔是什么坐搔? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮敬矩,結(jié)果婚禮上概行,老公的妹妹穿的比我還像新娘。我一直安慰自己弧岳,他們只是感情好凳忙,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布业踏。 她就那樣靜靜地躺著,像睡著了一般涧卵。 火紅的嫁衣襯著肌膚如雪勤家。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天柳恐,我揣著相機與錄音伐脖,去河邊找鬼。 笑死胎撤,一個胖子當著我的面吹牛晓殊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播伤提,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巫俺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肿男?” 一聲冷哼從身側(cè)響起介汹,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舶沛,沒想到半個月后嘹承,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡如庭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年叹卷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坪它。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡骤竹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出往毡,到底是詐尸還是另有隱情蒙揣,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布开瞭,位于F島的核電站懒震,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嗤详。R本人自食惡果不足惜个扰,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望葱色。 院中可真熱鬧锨匆,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舞痰。三九已至土榴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間响牛,已是汗流浹背玷禽。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呀打,地道東北人矢赁。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像贬丛,于是被迫代替她去往敵國和親撩银。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容