shiro权限绕过总结
date
Mar 16, 2022
slug
shiro-bypass-auth
status
Published
tags
Java安全
安全研究
summary
总结一下shiro权限绕过的内容
type
Post
重写doGetAuthenticationInfo(用户身份认证信息)方法导致的问题
总结一下:就是session的处理问题
代码例子如下:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException,NumberFormatException {
if (token.getPrincipal()==null){
throw new UnknownAccountException();
}
Integer studentId = Integer.valueOf((String) token.getPrincipal());
//取出数据库中的指定User
User user= Optional.ofNullable(userMapper.selectByStudentId(studentId)).orElseThrow(UnknownAccountException::new);
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user,user.getPassword(),getName());
Session session= SecurityUtils.getSubject().getSession();
//存到shiro的session中(对于Web来说本质是HttpSession)
session.setAttribute("USER_SESSION",user);
return info;
}
登陆处:
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(studentId,password);
try {
subject.login(token);
}
API身份校验:
if(!SecurityUtils.getSubject().isAuthenticated()) {
return resultJson.error(401,"未授权");
}
User user = CommonUtil.getUserFromShiroSession();
//其中的getUserFromShiroSession():
public static User getUserFromShiroSession(){
return (User)SecurityUtils.getSubject().getSession().getAttribute("USER_SESSION");
}
这里的逻辑是身份验证时,先验证当前的Subject是否已经授权,如果已经授权的话,获取当前用户采用了从shiro的session中获取的方法
这里会出现什么问题?
根据作者的调试,得出这样的结论:
即使登录失败,我们在doGetAuthenticationInfo
中设置的session属性依然可以生效。而且由于异常栈抛出的过程中并没有创建subject,也不会重新设置authenticated的状态。
这里的认证状态指的是下图这个变量:
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F2916e098-9a19-4e61-9436-a21da4d23d61%2FUntitled.png%3Fid%3D5c40dc33-2312-47cd-b929-dfbeba341721%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3Dprffhdw59PKLEUqpXuNcKe8JOgTY6NYqqodEwyIzH1Q?table=block&id=5c40dc33-2312-47cd-b929-dfbeba341721&cache=v2)
所以就会存在这样的一个问题:
当用户重复登录的时候(即使登陆失败),会改变session中的USER_SESSION的值,但是并不会改变用户isAuthenticated的状态(所以对应API的权限就会改变)
当A用户使用自己的账号登录成功之后(这时Subject.isAuthenticated()已经变成了true),带着登录成功的Session,尝试登录另一个用户B的账号,Shiro在
Subject.login()
的时候调用了我们重写的doGetAuthenticationInfo(AuthenticationToken token)
方法。这时候,Session中的USER_SESSION的值已经变成了用户B的信息,而且shiro这时并不会更新isAuthenticated的状态,这样一来用户A就可以绕开了身份验证,能够以用户B的身份访问其他的API
作者攻击的一个流程:
登陆一个已知用户(该用户不可使用对应用户的接口)→获得session→然后再次登陆对应权限admin的用户(即使该用户密码错误)→此时isAuthenticated无改变,但是session变成了admin用户的session→触发admin权限api
所以最好的方法就是修改api权限校验点:
获取当前用户的方法应该为,不再使用对应的session进行判断
(User) SecurityUtils.getSubject().getPrincipal()
这里是因为Subject中的principal只有在用户成功登录之后才进行更新。
shiro与spring组合下对uri处理差异导致的漏洞
用的这个demo,需要打包成war部署再进行测试,不然直接Springboot启动会报错,IDEA直接整就完事了:
org.syclover.srpingbootshiro.ShiroConfig
里面filter设置了相关的权限,admin路由还是需要权限校验的![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F942b359b-e5e5-47a8-8383-ccd48d582043%2FUntitled.png%3Fid%3D273f759a-9fda-4b3c-82ff-470de0f8e30f%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3Dbj5W1MPPmrjgokUjlQYXHUb21yI9v8MvFYMuZbUz5K8?table=block&id=273f759a-9fda-4b3c-82ff-470de0f8e30f&cache=v2)
一些小知识点:
设置权限的相关属性
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Faba7c6d5-202d-4d96-9cd7-9fc60b44f5ef%2FUntitled.png%3Fid%3Df37c22ce-10b8-41ca-8aad-75c937ee5839%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DHS2yPvGkfRtliazu3NuBcswRQe0umgc8CsPYznLRWVw?table=block&id=f37c22ce-10b8-41ca-8aad-75c937ee5839&cache=v2)
还有一些相关通配符
?:匹配一个字符
*:匹配零个或多个字符串
**:匹配路径中的零个或多个路径
对应的Controller需要修改一下
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F5b55b95b-d2dc-451b-b438-b0c86d7cb71c%2FUntitled.png%3Fid%3Daa7efd15-6dfb-43b2-96d7-8424fd9f7ba8%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3Dz9i7FePxnAizQQbju12oEmPTG8dbTgbZriMV5Gs54qw?table=block&id=aa7efd15-6dfb-43b2-96d7-8424fd9f7ba8&cache=v2)
CVE-2020-11989
- Apache Shiro < 1.5.3
- Spring 框架中只使用 Shiro 鉴权
直接访问admin路由下的内容肯定是不可行的
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Fa4839cce-7890-44c0-9e14-08a488496845%2FUntitled.png%3Fid%3Daeb3cdb4-19ef-4991-8e5a-86bd80afcc81%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DzraV2dr-k-TBU_R2ZQQrcfATL5Zsk38uLqZ8I0BTStY?table=block&id=aeb3cdb4-19ef-4991-8e5a-86bd80afcc81&cache=v2)
当然这个场景下需要一些限制条件,首先权限ant风格的配置需要是
*
而不是**
,同时controller需要接收的request参数(@PathVariable)的类型需要是String,否则将会出错。当数据包是这样的时候
GET /shiro_war/admin/gss%252fe HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Connection: close
Cache-Control: max-age=0
就可以触发权限绕过
可以调试查看,开始的触发点在
org.apache.shiro.web.util.WebUtils#getPathWithinApplication
在
getRequestUri
这一步的时候已经url解码完成了![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F60777fb4-2dd6-4d49-b804-fb89e4128c53%2FUntitled.png%3Fid%3Dcbdcb531-2026-4533-b55c-96b23aa9d488%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3Dj-6cbXyC9W3x6dWevP8RQcr9nky_RhOieth6FdmrvGE?table=block&id=cbdcb531-2026-4533-b55c-96b23aa9d488&cache=v2)
跟进这个
getRequestUri
函数看一下,此时处理的uri是这样的,拼接到shiro_war
下了,但是会经过normalize,decodeAndCleanUriString
两个函数的处理![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F34c4204e-85f4-45c8-8251-f0c090ac5002%2FUntitled.png%3Fid%3D3bea90f4-9f23-470b-9c59-4cf809cc0bb1%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DP_mcQg2k8wIOZKoM6M07_84ejNhiGmu3wrYTiHUPWcA?table=block&id=3bea90f4-9f23-470b-9c59-4cf809cc0bb1&cache=v2)
先看
decodeAndCleanUriString
做了什么,先进行了一遍url解码(此时两次URL编码已经解码完了),然后从解码的内容里面寻找;
如果找到;
截取;
之前的内容返回![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F09fadc49-997d-48c3-bf9d-46092b340e83%2FUntitled.png%3Fid%3D5cba8a02-51be-4171-8b5f-4bc68211bcba%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DYfYK4ALjJg21c3J5fl5qY9xUjNXm1iUwIGKy6yZcKnI?table=block&id=5cba8a02-51be-4171-8b5f-4bc68211bcba&cache=v2)
再经过normalize函数的处理,主要是对下面这几种符号做处理,跟Tomcat的normalize处理差不多
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F80c6e7e6-def5-4e83-987f-81c2438a5df7%2FUntitled.png%3Fid%3Dd2465db2-ff04-46b1-9a66-c4d85aa0651a%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DXyN130nmrlO1CA8YkMSZrZbX5kCrBdVM_xlb6h1P3kw?table=block&id=d2465db2-ff04-46b1-9a66-c4d85aa0651a&cache=v2)
处理之后从
/shiro_war/admin/gss%252fe
—> /shiro_war//admin/gss/e
,传递的2次编码url已经被完全decode。下一步就是Shiro的filter对请求资源的权限校验,主要的步骤跟进AntPathMatcher.class#doMatch
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Fb68c55bb-2f30-4975-96c0-d8614242d655%2FUntitled.png%3Fid%3De59d6576-b2b6-44c8-8c14-e9cc709afbf0%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DEkzgrke7wrP-3Nm2U5sxq1nPeYlGGHWy8_gTkexirv8?table=block&id=e59d6576-b2b6-44c8-8c14-e9cc709afbf0&cache=v2)
此时该函数会根据Shiro里面配置的ant来进行匹配,因为配置里面存在
admin/*
所以会对此进行匹配然后将路径拆分一个个进行匹配,通过
matchStrings
函数与pathDirs
数组中的值进行匹配,匹配失败会直接返回false(也就是证明没有权限问题)![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Fb4842d22-5cdb-4a61-b7f6-1305485c2016%2FUntitled.png%3Fid%3D02812cb8-6905-48e6-a85f-271586a7a39d%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DNM2p622fECSYDPLZL9ZVTPkPGrDOaWdTMOJklT9Mmuc?table=block&id=02812cb8-6905-48e6-a85f-271586a7a39d&cache=v2)
如果匹配到了则会每次使
pattIdxStart++
,例如这里的pattern数组分为[admin,*]
,则会依次匹配到admin
与gss
,那么pattIdxStart
为2是pattern数组的末尾索引,这里为1
![notion image](https://www.notion.so/image/https%3A%2F%2Fi.loli.net%2F2021%2F02%2F09%2FgLVImufOSNJsFlB.jpg?table=block&id=92dfd186-5cd0-4db7-a105-6f055515fd1e&cache=v2)
而在之后的判断中,赋值后的pattIdxStart > pattIdxEnd返回false绕过了判断
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F1e2abd6a-e46b-4c41-ae94-4230b598dc19%2FUntitled.png%3Fid%3D401d934e-bed1-418d-b17e-2c71973bf205%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DRcBRu8Z2wvqVvSh4TolYv4hy1k93Pnc6ZmkCB4RiGXw?table=block&id=401d934e-bed1-418d-b17e-2c71973bf205&cache=v2)
也就是说,
/*
这种匹配只能命中/admin/gss
这种格式,无法命中/admin/gss/xxx
返回false之后就能触发到相关路由了,在这个函数里可以找到对应的处理结果,Spring的url处理模块应该是
org.springframework.web.util.UrlPathHelper#getLookupPathForRequest(javax.servlet.http.HttpServletRequest)
可以看到对应的DispatchPath
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Fb5e452c7-5be6-462f-a277-c3fc8e731d69%2FUntitled.png%3Fid%3D99cdd22e-5594-483f-9905-d5f9e8a6065d%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DNrPUHcJheMIil2sUwMU3U5I5smghUBWasq9Q8Uh0NN4?table=block&id=99cdd22e-5594-483f-9905-d5f9e8a6065d&cache=v2)
但是从结果看,可以发现本质上Spring框架只对内容进行了一次的url编码处理(下图中还剩下一个%2f没有解码),但是Shiro框架处理的时候会全部进行解码,这个trick可以记录一下
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F835f90cf-910e-4490-9a8e-6f9adcdf183d%2FUntitled.png%3Fid%3D9cb8f478-c7de-45e3-bf94-1f445e506cea%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DNtKdutcJtKDHXQNV9W84n6im_LtBrhOMDPCSWaIqGS0?table=block&id=9cb8f478-c7de-45e3-bf94-1f445e506cea&cache=v2)
修复:
入口的函数修改成这样:
public static String getPathWithinApplication(HttpServletRequest request) {
return normalize(removeSemicolon(getServletPath(request) + getPathInfo(request)));
}
采用标准的 getServletPath 和 getPathInfo 进行uri处理,这样
pattIdxStart
与pattIdxEnd
就是相同的数值![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F6dbd5873-8ff8-4f94-b456-50c79616e1ae%2FUntitled.png%3Fid%3D9e091b66-9d70-4be9-8a3a-6a5aa22c7862%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DVPkdHEjqnT0q8BWMMuDHkWylTksCFBqYkvS5nQWuEGY?table=block&id=9e091b66-9d70-4be9-8a3a-6a5aa22c7862&cache=v2)
CVE-2020-13933
- Apache Shiro < 1.6.0
- Spring 框架中只使用 Shiro 鉴权
问题出现在补丁中的removeSemicolon函数,触发的payload如下:
GET /shiro_war/admin/%3beee HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Connection: close
Cache-Control: max-age=0
调试可以发现经过removeSemicolon函数之后,它就是返回”;”之前的内容,实际上是为了处理GET请求中
”/admin/;jessid=xxxx”
这样的需求此时path为
/admin
,因此也不属于不属于请求/admin/*
下的资源,因此不会被鉴权,此时会导致这个条件其实不通过,也就是不属于/admin/*
资源的意思,最后执行到return false![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Ff1cc4b9e-aeaa-4850-877b-4fa5760b8c06%2FUntitled.png%3Fid%3D184aad94-7f4b-4d22-a115-9afeca820a17%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3D0C8jIDWiQw5EUX5LXrg3orauQjTOrklXx5aS8m7mjQ0?table=block&id=184aad94-7f4b-4d22-a115-9afeca820a17&cache=v2)
最后就可以直接进入contrller了
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Fd46b092b-bd77-487a-a877-33f901b5e5e0%2FUntitled.png%3Fid%3D7579ea3e-165a-4dd0-8e05-52f115bf0a03%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3D6L8JCopcz6gDWrXlOt2zBd1rA8hV71yjAiwEwoTDlE8?table=block&id=7579ea3e-165a-4dd0-8e05-52f115bf0a03&cache=v2)
修复:
是在上面漏洞的流程走完之后,添加上一个
InvalidRequestFilter
过滤器类,在处理到Spring框架之前会过滤一些内容![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F57e6b491-665d-413d-8442-8445240211b4%2FUntitled.png%3Fid%3Dd2d3d3f0-4844-470f-8d8f-980ab48fe0f5%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DHHGDC0R198qYv0tK4YDE_GMJLqgeFqlJ7beg8nicZsE?table=block&id=d2d3d3f0-4844-470f-8d8f-980ab48fe0f5&cache=v2)
监测到就直接抛400了
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Ff4a1ff08-b756-431f-97a2-a933059fee3c%2FUntitled.png%3Fid%3D073ab569-cc40-4bd0-98e1-0d4e2974fbe6%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DCENwtOcwRfrB6WNKo_4Z2vMLpq3t3imrRJuWHKYw3X8?table=block&id=073ab569-cc40-4bd0-98e1-0d4e2974fbe6&cache=v2)
CVE-2020-17523
- Apache Shiro < 1.7.1
- Spring 框架中只使用 Shiro 鉴权
这次出发的payload是
GET /shiro_war/admin/%20 HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Connection: close
Cache-Control: max-age=0
此时可以访问对应的接口
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Febe56d2e-8eea-4c1e-b206-21c4cde14dfc%2FUntitled.png%3Fid%3D668366a9-2e81-40f0-bd69-16833b68c076%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DxIVj21csickThS-greG1Nq6iqyVSNMt8JOsFtjk9gD4?table=block&id=668366a9-2e81-40f0-bd69-16833b68c076&cache=v2)
继续跟doMatch方法,发现处理之后的path变量时代有一个空格的
/admin/
执行到
/Users/4me/.m2/repository/org/apache/shiro/shiro-core/1.6.0/shiro-core-1.6.0-sources.jar!/org/apache/shiro/util/AntPathMatcher.java:144
这个点的时候会进行一次匹配,但是并不符合,然后就进入下面返回false的流程里面了,导致了绕过,又因为没有相关奇怪的符号,就导致之前的那个补丁也绕过了![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F7381445a-577c-45e7-9855-43dbac36df29%2FUntitled.png%3Fid%3Df4134b39-1c25-45ea-b5d6-8795085fbad6%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DY0xGCPO01P5PUVniKASeamporj99g-vTwU79F4SeIjM?table=block&id=f4134b39-1c25-45ea-b5d6-8795085fbad6&cache=v2)
主要原因还是在这个处理逻辑上面的循环函数里面,由于path只包含一个元素,因此我们的
pathIdxStart
与pathIdxEnd
初值均为0;经过一次循环后,pathIdxStart
自增为1,跳出了这个循环判断,而且对path变量处理的时候会自动trim,导致了pathIdxEnd
计算的时候没有把空格算上![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F86bcf2ec-de8a-4dda-830b-06b8a17dca02%2FUntitled.png%3Fid%3Dd2dcae70-7cfb-4727-bf44-f3ca8aaa86b3%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DJI6XtX3wAbwtHUeGItyOATm5K4qoohGfX2Dv8P8zxQM?table=block&id=d2dcae70-7cfb-4727-bf44-f3ca8aaa86b3&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F427fcebd-50fc-4b7e-b2b0-67820045a883%2FUntitled.png%3Fid%3D587e57c3-2ae2-4dcf-a226-6a971b479599%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DqhCREnIrnWdmCL3qGsMK01I7sfo0-daWZDhyypGM0HM?table=block&id=587e57c3-2ae2-4dcf-a226-6a971b479599&cache=v2)
所以在寻找绕过的方法的时候,可以针对这个trim函数可以处理的空格入手,多找几个,就多了几种操作方式,有人测试了,发现其他空格不太可行
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2F5c5fc0f5-9a0c-4f11-8cc8-73175f90bf60%2FUntitled.png%3Fid%3Db1baf6c6-5c8f-4eb2-a6bf-a3929eb5afe7%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DUEuxtpRjwhucHixNGVvVnoMYYTQOWSZVZEiQZwC78_Q?table=block&id=b1baf6c6-5c8f-4eb2-a6bf-a3929eb5afe7&cache=v2)
修复:
默认不进行trim操作
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Ff02ca4a6-46ec-4ec1-ab8c-e8560136ee51%2FUntitled.png%3Fid%3Df4fedd3c-7eb4-4f57-9bf5-715fc3d24cec%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3DRK5-tuXw3pmOVnw5lTYphnJDEi-5oib9617cTuCMJIM?table=block&id=f4fedd3c-7eb4-4f57-9bf5-715fc3d24cec&cache=v2)
总结
1.关键处理函数在
org.apache.shiro.util.AntPathMatcher#doMatch
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2Fc113620e-b4a6-4a92-bee1-d70b242f1a2f%2Fb04db145-af85-4057-88b7-f38a3ca5cd87%2FUntitled.png%3Fid%3Dd941b5a7-1df8-4625-88bc-ddbe4ee5d8fa%26table%3Dblock%26spaceId%3Dc113620e-b4a6-4a92-bee1-d70b242f1a2f%26expirationTimestamp%3D1722088800000%26signature%3Dt9BqtOmxKY1tS_B-hrH8XO4obGjq302RVIvb14cXsHg?table=block&id=d941b5a7-1df8-4625-88bc-ddbe4ee5d8fa&cache=v2)