본문 바로가기
Hack/Web

Spring에서 Matrix Parameter를 지원함에 따라 발생 가능한 취약점

by Becoming a Hacker 2022. 9. 9.
반응형

Matrix Parameter

대부분의 웹 서버에서는 아래와 같은 Query String을 이용하여 Parameter를 처리합니다.

Scheme:host:port/path?key=value&key=value

https://hacksms.tistory.com:443/write?title=Hello&content=World

 

이러한 Query String을 대체할 수 있는 새로운 Parameter 방식이 추가되었는데, 이러한 방식을 Matrix Parameter라고 합니다. Matrix Parameter는 반드시 경로의 마지막이 아닌 원하는 위치에 Parameter를 작성할 수 있다는 특징을 갖고 있습니다.

Scheme:host:port/path;key=value/path2;key=value

https://hacksms.tistory.com:443/main;title=Hello/write;content=World

※ 해당 방식은 웹 표준이 아님  (잘못된 정보일 수도 있음!)

 

모든 환경에서 Matrix Parameter를 지원하는 것은 아니지만, Spring의 경우 3.2 버전부터 해당 방식을 지원하도록 추가가 되었습니다.

 

A Quick Guide to Spring MVC Matrix Variables | Baeldung

A short guide about Spring MVC matrix variables, explaining what they are and how to use them to simplify our requests.

www.baeldung.com

 

Matrix Parameter Vulnerability

즉, Matrix Parameter의 특성은 경로마다 Parameter를 삽입할 수 있다는 점 입니다. 그런데 이러한 특성으로 인해 경로에 따른 권한 검증 단계에서 Authentication Bypass 취약점이 발생할 수 있습니다.

 

Sample Code (Spring Boot + Kotlin)

class LoginInterceptor : HandlerInterceptor {
    override fun preHandle(request: HttpServletRequest, response : HttpServletResponse, handler: Any): Boolean{
        // check loginId in session

        val uri = request.requestURI
        val path = uri.split("/")[1]

        val authentication_list = arrayListOf<String>("main","assetsManagement", "financialLedger", "userManagement")
        for(str in authentication_list){
            if(path.equals(str)){
                val session = request.getSession()
                var loginCheck = session.getAttribute("loginId")
                if(loginCheck==null){
                    response.sendRedirect("/login")
                    return false
                }
            }
        }
        return true
    }
}

@Configuration
class WebConfig: WebMvcConfigurer{
    override fun addInterceptors(registry: InterceptorRegistry) {
        registry.addInterceptor(LoginInterceptor())
    }
}

 

Sample Code의 경우 특정 경로(main, assetsManagement, financialLedger, userManagement)로 접근 시, 세션을 통해 로그인 여부를 확인한 뒤, 결과에 따라 Controller로 넘겨주거나 login Page로 Redirect 시키는 Code입니다. 

 

여기서 취약점이 발생하는 구간은 "Request URI에서 시작 경로를 추출한 뒤, 해당 값을 인증이 필요한 문자열과 비교하는 과정"에서 발생합니다.

val uri = request.requestURI
val path = uri.split("/")[1]

val authentication_list = arrayListOf<String>("main","assetsManagement", "financialLedger", "userManagement")
for(str in authentication_list){
	if(path.equals(str)){

 

단순히 코드로만 확인을 했을 때는 이 부분에서 왜 취약점이 발생하는지 이해가 되지 않을 수도 있는데요.

 

Spring에서는 Matrix Parameter가 사용이 가능하기 때문에 서버에서 받아들이는 실제 경로와 Request URI간의 차이가 발생할 수 있기 때문입니다.

 

Matrix Parameter의 경우 ;(Semicolon) 이후부터 /(Slash)까지의 문자열을 Parameter로 인식합니다. 그러나 Query String이 표준인 서버에서는 별도로 Matrix Parameter에 대한 처리 로직을 작성하지 않으면 ;과 / 사이의 문자열도 모두 경로로 처리되기 때문에 차이가 발생하게 됩니다.

Matrix Parameter : /main;title=Hello/

Query String : /main;title=Hello/

 

다시 Sample Code로 돌아와서 "/main"이 아닌 "/main;"로 접근할 경우 path 변수에 담기는 값은 "main;" 이기 때문에 로그인 검사 로직을 우회하여 해당 경로에 접근할 수 있게 됩니다.

val uri = request.requestURI // Reqeust URI -> 127.0.0.1:8080/main;
val path = uri.split("/")[1] // split[1] result -> main;

val authentication_list = arrayListOf<String>("main","assetsManagement", "financialLedger", "userManagement")
for(str in authentication_list){
	if(path.equals(str)){ // "main;".equals("main") -> False

인증 과정 우회

 

2018년 Blackhat에서 Orange Tsai가 이와 관련된 취약점에 대한 Case Study를 발표한 적이 있는데 해당 자료가 궁금하신 분들을 이 링크를 클릭해주세요.

 

 

 

댓글