shiro历史漏洞分析—CVE-2020-1957漏洞

声明

出品|先知社区(ID:alter99)

以下内容,来自先知社区的alter99作者原创,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,长白山攻防实验室以及文章作者不承担任何责任。

CVE-2020-1957

漏洞信息

漏洞编号:

CVE-2020-1957/CNVD-2020-20984/SHIRO-682
影响版本:shiro < 1.5.2
漏洞描述:利用Shiro和Spring对URL的处理的差异化,越权并成功访问。
漏洞补丁:Commit Commit Commit
参考:Shiro权限绕过漏洞详细分析Ruil1n师傅

漏洞分析

SHIRO-682

本漏洞起源于 SHIRO-682。在Spring中,/resource/xx与/resource/xx/都会被截成/resource/xx以访问相应资源;在shiro中,/resource/xx与/resource/xx/被视为两个不同路径。所以在Spring集成shiro时,只需要在访问路径后添加/就存在绕过权限校验的可能。

下面通过复现进行分析(分析、测试版本1.4.2):首先shiro.ini中[urls]配置如下:

[urls]# anon:匿名拦截器,不需登录就能访问,一般用于静态资源,或者移动端接口。# authc:登录拦截器,需要登录认证才能访问的资源。/login.jsp = authc/logout = logout/toJsonPOJO = authc, perms["audit:list"]/** = anon

输入/toJsonPOJO时,shiro对其进行判断,从shior.ini或其他配置中进行匹配。当匹配到/toJsonPOJO时,匹配成功,跳出循环。

此时,跳转至登陆界面。
输入/toJsonPOJO/时,shiro对其进行判断,当匹配到/toJsonPOJO时,匹配失败,继续匹配;当匹配到/**时,匹配成功,跳出循环。

接着到了springframework中的判断,这里/toJson-POJO/和/toJsonPOJO是可以匹配成功的

此时,成功绕过

其他绕过方式

除了上面的绕过方式,本CVE还存在另一个绕过。利用的是shiro和spring对url中的 ; 处理的差异进行绕过并成功访问。分析、测试版本1.4.2

绕过分析

首先进入Shiro中,首先在

org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver.class#getChain处下断点,进行调试,访问http://localhost:8080/xx/..;/toJsonPOJO

单步调试进入this.getPathWithinApplicat-ion(request),在WebUtils#getPathWithinApplicat-ion()中,通过getContextPath(request),获取到上下文信息后,再用getRequestUri(request)获取具体的uri。进入getRequestUri()方法,在return前,获取到的uri为/xx/..;/toJsonPOJO

接下来分析一下return normalize(decodeAndClean-UriString(request, uri));

首先进入decodeAndCleanUriString

传入的参数uri是/xx/..;/toJsonPOJO,然后通过语句int semicolonIndex= uri.indexOf(59);找出uri中分号的位置,59也就是;的ASCII码

如果uri中有分号,就返回分号前的字段,否则返回整个uri。

接着进入normalize,参数uri已经变成/xx/..,normalize内部对传入的路径进行标准化规范处理,相关操作包括替换反斜线、替换//为/等,最后得到返回的uri

此时return normalize(decodeAndCleanUriString-(request, uri));结果为/xx/..,也就是说getRequestUri(request)获取的uri为/xx/..

一路回到getChain,经过上面的步骤,得到requestURI值为/xx/..,接下来在while循环里使用pathMatches(pathPattern, requestURI)进行权限校验,此时只有/**能够与/xx/..匹配成功,/**是anon权限,不需要登陆就能访问,绕过了/toJsonPOJO的authc权限

此时Shiro部分的权限绕过了,那么Spring部分的路径是怎么匹配的呢?

url经过shiro的处理认证通过后,就会进入spring中进行解析,我们在UrlPathHelper#getLookupPath-ForRequest下断点

先进入getPathWithinApplication(),通过this.get-RequestUri(request)获取uri

获取到的uri值为/xx/..;/toJsonPOJO,在return之前进入decodeAndCleanUriString(request, uri)

传进来的参数uri为/xx/..;/toJsonPOJO,经过removeSemicolonContent(uri)后移除uri中/与/之间的的分号以及分号后面的内容;

经过decodeRequestString(request, uri)后对uri进行解码;经过getSanitized-Path(uri)后将路径中//替换为/。此时返回的uri值为/xx/../toJsonPOJO

步入getPathWithinServletMapping()后,传入的参数pathWithinApp值为/xx/../toJsonPOJO。

依次通过UrlPathHelper#getServletPath

HttpServletRequestWrapper#getServletPath

Request#getServletPath获取到我们实际访问的url:http://localhost:8080/toJsonPOJO后返回,最终实现绕过权限访问

经过测试当uri为

123;/..;345/;../.;/alter/..;/;/;///////;/;/;awdwadwa/toJsonPOJO时,Shiro对/123进行权限验证;

Spring的org.springframework.web.util.UrlPathHelper中,getPathWithinApplication(request)值为

/123/.././alter/../toJsonPOJO;

this.getPathWithinServletMapping(request, pathWithinApp)值为/toJsonPOJO,可以进行绕过

上面这个payload只能在较低版本的Spring Boot上使用。

根据Ruil1n 师傅介绍:当Spring Boot版本在小于等于2.3.0.RELEASE的情况下,alwaysUseFullPath为默认值false,这会使得其获取ServletPath,所以在路由匹配时相当于会进行路径标准化包括对%2e解码以及处理跨目录,这可能导致身份验证绕过。

而反过来由于高版本将alwaysUseFullPath自动配置成了true从而开启全路径,又可能导致一些安全问题。

所以在高版本上只能试着寻找逻辑上有没有漏洞,然后进行绕过。比如程序配置了访问路径/alter/** 为 anon,但是指定了其中的一个/alter/page为 authc。这时在不跳目录的情况下,可以使用如下请求绕过:http://127.0.0.1:8080/alter//;aaaa/;...///////;/;/;awdwadwa/page

漏洞修复

先是在Commit的PathMatchingFilter#pathsMatch和PathMatchingFilterCha-inResolver#getChain方法中添加了对访问路径后缀为/的支持

然后在Commit,除了endsWith还添加了equals的判断。是修复由于上一次提交,导致访问路径为/时抛出的异常。

在Commit中,shiro使用request.getContextPath()、request.getServletPath-()、request.getPathInfo()拼接构造uri替代request.getRequestURI()来修复; 绕过

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容