Table of contents
1 CVE-2023-20860 背景
1.1 涉及既 library 版本
呢個漏洞係同 org.springframework:spring-webmvc
有關。有問題既版本包括 [5.3.0,5.3.26)
、[6.0.0,6.0.7)
,亦即係:
5.3.0
至 5.3.25
6.0.0
至 6.0.6
已修復既版本包括:
註:6.x
係用於 Spring Boot 3.x
。
1.2 漏洞涉及既安全問題
根據 CVE 既描述,當使用左 mvcRequestMatcher
配置 Spring Security 既時候用左 un-prefixed double wildcard pattern(**
),Spring 背後所產生既實際 Spring MVC 配置會同我地既 Spring Security 有出入,最終有可能導致個 Spring app 允許未經授權既訪問。
2 建立測試項目
2.1 Maven dependencies
- Maven parent POM:
spring-boot-starter-parent
- Dependencies
spring-boot-starter-web
spring-boot-starter-security
2.2 HTTP APIs
Request method | Request path | 測試結果期望 |
---|
GET | /public | 呢個 endpoint 唔應該需要登入驗證。 |
GET | /secure | 呢個 endpoint 應該需要登入驗證。 |
2.3 寫 Java code
2.3.1 Controller
BusinessController.java
:
1@RestController
2public class BusinessController {
3
4 @GetMapping("public")
5 public String _public() {
6 return "This is a public endpoint. You should see this without logging in.";
7 }
8
9 @GetMapping("secure")
10 public String secure() {
11 return "This is a secure endpoint. You should NOT see this without logging in.";
12 }
13}
2.3.2 Spring Security config class
SecurityConfiguration.java
:
1@Configuration
2public class SecurityConfiguration {
3
4 @Bean
5 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
6 return http
7 .authorizeHttpRequests().mvcMatchers("/public").permitAll()
8 .and()
9 .authorizeHttpRequests().mvcMatchers("/**").authenticated()
10 .and()
11 .httpBasic()
12 .and()
13 .build();
14 }
15}
另一個寫法:
1@Configuration
2public class SecurityConfiguration {
3
4 @Bean
5 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
6 return http
7 .authorizeHttpRequests()
8 .mvcMatchers("/public").permitAll()
9 .mvcMatchers("/**").authenticated()
10 .and()
11 .httpBasic()
12 .and()
13 .build();
14 }
15}
再另一個寫法:
1@Configuration
2public class SecurityConfiguration {
3
4 @Bean
5 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
6 return http
7 .authorizeHttpRequests(authorize -> authorize
8 .mvcMatchers("/public").permitAll()
9 .mvcMatchers("/**").authenticated())
10 .httpBasic()
11 .and()
12 .build();
13 }
14}
3 測試結果
3.1 使用有漏洞既版本
以下係有漏洞既版本:
spring-boot-starter-security 2.7.1
spring-webmvc 5.3.21
3.1.1 測試結果:Permit 特定 endpoints、authenticate wildcard
mvcMatchers(<some paths>).permitAll()
mvcMatchers(<wildcard>).authenticated()
Implementation | 解釋 | 結果 |
---|
Permit public 、authenticate ** | 兩者都冇 / 開頭 | ❌ /secure 唔需要登入,存在漏洞。 |
Permit /public 、authenticate /** | 兩者都有 / 開頭 | ✅ 符合測試結果期望。 |
Permit public 、authenticate /** | 其中一個有 / 開頭 | ❌ /public 需要登入,過分安全。 |
Permit /public 、authenticate ** | 其中一個有 / 開頭 | ❌ /secure 唔需要登入,存在漏洞。 |
Permit public 、authenticate * | 兩者都冇 / 開頭,單 * 字元 | ❌ /secure 唔需要登入,存在漏洞。 |
Permit /public 、authenticate /* | 兩者都有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Permit public 、authenticate /* | 其中一個有 / 開頭,單 * 字元 | ❌ /public 需要登入,過分安全。 |
Permit /public 、authenticate * | 其中一個有 / 開頭,單 * 字元 | ❌ /secure 唔需要登入,存在漏洞。 |
3.1.2 測試結果:Authenticate 特定 endpoints、permit wildcard
mvcMatchers(<some paths>).authenticated()
mvcMatchers(<wildcard>).permitAll()
Implementation | 解釋 | 結果 |
---|
Authenticate secure 、permit ** | 兩者都冇 / 開頭 | ❌ /secure 唔需要登入,存在漏洞。 |
Authenticate /secure 、permit /** | 兩者都有 / 開頭 | ✅ 符合測試結果期望。 |
Authenticate secure 、permit /** | 其中一個有 / 開頭 | ❌ /secure 唔需要登入,存在漏洞。 |
Authenticate /secure 、permit ** | 其中一個有 / 開頭 | ✅ 符合測試結果期望。 |
Authenticate secure 、permit * | 兩者都冇 / 開頭,單 * 字元 | ❌ /secure 唔需要登入,存在漏洞。 |
Authenticate /secure 、permit /* | 兩者都有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Authenticate secure 、permit /* | 其中一個有 / 開頭,單 * 字元 | ❌ /secure 唔需要登入,存在漏洞。 |
Authenticate /secure 、permit * | 其中一個有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
3.2 使用已修復既版本
用已修復既 spring-webmvc
版本覆蓋項目現有既版本:
spring-boot-starter-security 2.7.1
- Spring Security (multiple libraries)
5.7.2
spring-webmvc 5.3.26
3.2.1 測試結果:Permit 特定 endpoints、authenticate wildcard
mvcMatchers(<some paths>).permitAll()
mvcMatchers(<wildcard>).authenticated()
Implementation | Test case | 結果 |
---|
Permit public 、authenticate ** | 兩者都冇 / 開頭 | ✅ 符合測試結果期望。 |
Permit /public 、authenticate /** | 兩者都有 / 開頭 | ✅ 符合測試結果期望。 |
Permit public 、authenticate /** | 其中一個有 / 開頭 | ✅ 符合測試結果期望。 |
Permit /public 、authenticate ** | 其中一個有 / 開頭 | ✅ 符合測試結果期望。 |
Permit public 、authenticate * | 兩者都冇 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Permit /public 、authenticate /* | 兩者都有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Permit public 、authenticate /* | 其中一個有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Permit /public 、authenticate * | 其中一個有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
3.2.2 測試結果:Authenticate 特定 endpoints、permit wildcard
mvcMatchers(<some paths>).authenticated()
mvcMatchers(<wildcard>).permitAll()
Implementation | Test case | 結果 |
---|
Authenticate secure 、permit ** | 兩者都冇 / 開頭 | ✅ 符合測試結果期望。 |
Authenticate /secure 、permit /** | 兩者都有 / 開頭 | ✅ 符合測試結果期望。 |
Authenticate secure 、permit /** | 其中一個有 / 開頭 | ✅ 符合測試結果期望。 |
Authenticate /secure 、permit ** | 其中一個有 / 開頭 | ✅ 符合測試結果期望。 |
Authenticate secure 、permit * | 兩者都冇 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Authenticate /secure 、permit /* | 兩者都有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Authenticate secure 、permit /* | 其中一個有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
Authenticate /secure 、permit * | 其中一個有 / 開頭,單 * 字元 | ✅ 符合測試結果期望。 |
4 參考資料