You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SaToken version <= 1.36.0
and (SpringBoot version >= 2.3.1.RELEASE or Spring version >= 5.3.0)
fixed version:
version = 1.37.0
description
When SaToken version <= 1.36.0, together with SpringBoot version >= 2.3.1.RELEASE or Spring version >= 5.3.0, a specially crafted HTTP request may cause an authentication bypass. The authentication bypass occurs when SaToken and Spring Boot/Spring are using different pattern-matching techniques. Update to SaToken 1.37.0 or set the following Spring Boot configuration value: spring.mvc.pathmatch.matching-strategy = ant_path_matcher
复现步骤:
First register the user, the permission is:user
(首先,注册用户,权限是user)
@Component
public class StpInterfaceImpl implements StpInterface {
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
List<String> list = new ArrayList<String>();
list.add("user");
return list;
}
}
Register an interceptor whose interception address is:/admin/**,Need permission:admin
(注册一个拦截器,地址是/admin/**,需要权限admin)
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor(handler -> {
SaRouter
.match("/**")
.notMatch("/user/doLogin")
.check(r -> StpUtil.checkLogin());
SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
})).addPathPatterns("/**");
}
}
Then write a login interface, an admin interface, the interface address is:/admin/**
(然后写一个登录接口,一个admin接口,admin接口地址是/admin/**)
@RestController
public class UserController {
// Test login, browser access: http://localhost:8081/user/doLogin?username=zhang&password=123456
@RequestMapping("/user/doLogin")
public String doLogin(String username, String password) {
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return "success";
}
return "fail";
}
@RequestMapping("/admin/**")
public String getPassword() {
return "flag{m4ra7h0n}";
}
}
Login first(http://localhost:8081/user/doLogin?username=zhang&password=123456)
(首先登录)
Then access: /admin/.. without url normalizing
(然后访问/admin/..,使用url未被curl/浏览器标准化的访问方式)
The text was updated successfully, but these errors were encountered:
m4ra7h0n
changed the title
SaToken和Spring对uri处理的差异化引发的越权漏洞
SaToken和Spring对uri处理的差异化引发的越权漏洞(SaToken and Spring's differential handling of URIs raises overreach vulnerabilities)
Sep 24, 2023
m4ra7h0n
changed the title
SaToken和Spring对uri处理的差异化引发的越权漏洞(SaToken and Spring's differential handling of URIs raises overreach vulnerabilities)
SaToken和Spring对uri处理的差异化引发的越权漏洞(SaToken and Spring's differential handling of URIs raises authorization bypass vulnerabilities)
Sep 29, 2023
affected version:
SaToken version <= 1.36.0
and (SpringBoot version >= 2.3.1.RELEASE or Spring version >= 5.3.0)
fixed version:
version = 1.37.0
description
When SaToken version <= 1.36.0, together with SpringBoot version >= 2.3.1.RELEASE or Spring version >= 5.3.0, a specially crafted HTTP request may cause an authentication bypass. The authentication bypass occurs when SaToken and Spring Boot/Spring are using different pattern-matching techniques. Update to SaToken 1.37.0 or set the following Spring Boot configuration value:
spring.mvc.pathmatch.matching-strategy = ant_path_matcher
复现步骤:
First register the user, the permission is:
user
(首先,注册用户,权限是user)
Register an interceptor whose interception address is:
/admin/**
,Need permission:admin
(注册一个拦截器,地址是
/admin/**
,需要权限admin
)Then write a login interface, an admin interface, the interface address is:
/admin/**
(然后写一个登录接口,一个admin接口,admin接口地址是
/admin/**
)Login first(
http://localhost:8081/user/doLogin?username=zhang&password=123456
)(首先登录)
Then access:
/admin/..
without url normalizing(然后访问
/admin/..
,使用url未被curl/浏览器标准化的访问方式)curl -H "Cookie: satoken=42ae3a64-974e-4e6e-8a9a-6a9e41c83396" --path-as-is http://localhost:8081/admin/..
root cause
其根本原因在于
SaRequestForServlet.getRequestPath()
函数使用HttpServletRequest.getServletPath()
获取标准化的servlet path,处理了跨目录。而Spring与SpringBoot情况如下(未处理跨目录):
1.SpringBoot版本>=2.3.1.RELEASE时
org.springframework.web.servlet.mvc.method.RequestMappingInfo#getMatchingCondition()
中使用PatternsCondition.getMatchingCondition()
获取匹配的路径,其内部PathHelper.getLookupPathForRequest()
函数查找映射时alwaysUseFullPath=true
(这里是SpringBoot自动装配配置的,版本<=2.3.0.RELEASE时使用spring中默认的false),其使用getPathWithinApplication()
查找url,未处理跨目录,而此时Spring版本<5.3.02.当Spring版本>=5.3.0时Url匹配模式直接从
PatternsCondition.getMatchingCondition();
转变成了PathPatternsRequestCondition.getMatchingCondition()
,这会导致其使用ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication();
查找url,同样未处理跨目录。Springboot版本>=2.3.1.RELEASE时引发的路径绕过可参考http://rui0.cn/archives/1643
spring5.3.0版本更新文档可参考https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc
此漏洞可参考CVE-2023-22602
修复参考apache/shiro@e167a71
The text was updated successfully, but these errors were encountered: