ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Error Handling: Mustache 취약점 발견 (w/Springboot)
    에러 핸들링 2022. 6. 21. 22:52

    Error Handling: Mustache 취약점 발견 (w/Springboot)

    개요


    오늘 스프링부트 책을 보면서 공부하다가 보니 이상한 점이 있었습니다. 특정 기능 결과 화면이 책의 예제와 다르게 나오는 거에요. 처음엔 당연히 '내가 뭘 잘못했나?'라고 생각했는데 출력값을 보다 보니, 제 코드가 아닌 다른 부분에서 뭔가 잘못되었다는 확신이 들었어요.
    처음에는 블로그 서칭을 해봤는데, 문제 해결책은 제시해주고 있는데 명쾌한 답이 없더라고요. 사실 빨리 해결하고 넘어가고 싶었지만, 이유를 모르면 똑같은 문제에 봉착할 거란 생각이 들었어요. 그리고 공부가 목적인데 공부가 안되면 이상하잖아요?ㅋㅋ... 그래서 해당 기능과 연관된 라이브러리들을 하나씩 열어보고, 깃헙에 들어가서 이슈를 보면서 범인을 찾아봤습니다.
    결론은 사용하고 있는 템플릿 엔진인 Mustache 라이브러리의 취약점이었는데, 주의해야겠다는 생각이 들어서 블로그로 남기기로 했습니다.

    TL;DR


    어떤 상황이었나?

    oauth2로 구글 로그인을 수행하고, 인증 받은 회원명("userName")을 띄우는 부분이었습니다.

    어떤 문제가 있었나?

    회원명 부분에 제 이름이 아닌 숫자열이 떴습니다. 그 숫자열의 정체는... 제 WindowsOS Machine Name이었습니다. 😱

    어떤 확인을 했나?

    일단 제대로 된 값을 넘겨받았는지부터 확인했습니다.

    1. 일단 oauth2로부터 회원 데이터를 받자 마자 entity부터 saveOrUpdate 했기 때문에 DB에 제대로 된 값이 들어갔는지, 확인 결과: 정상
    2. HttpSession 객체가 담고 있는 값, 확인 결과: 정상
    3. 그걸 넘겨받은 Model, 확인 결과: 정상
    4. 그걸 View로 넘겨주기 직전에 Controller에서 확인하고, 확인 결과: 정상
    5. View에서 제대로 된 값을 넘겨받았나? 확인 결과: 비정상

    다른 포스팅들에서는 이유는 모르겠지만 변수명을 바꾸면 제대로 해결된다고 하더라고요. 그래서 바꿔봤습니다.

    1. 컨트롤러에서 model.setAttribute("userName", httpSession.getName()); => model.setAttribute("name", httpSession.getName())로 변경
    2. 템플릿 엔진(mustache) 코드에서 "userName" => "name"으로 변경.
    3. 실행 결과: 정상

    하지만 의문은 풀리지 않았습니다.

    왜 userName은 안될까?
    그리고 (굉장히 찝찝하게) 하필이면 내 컴퓨터 이름과 일치한 숫자가 뜰까?...

    그래서 다음 실험을 해봤습니다. 컨트롤러가 넘겨준 값을 찍고 있긴 한건가?

    1. 컨트롤러에서 model.setAttribute("userName", null);로 변경.
    2. mustache에서도 다시 "userName"으로 변경.
    3. 실행 결과: 정상

    ???!????!!?... 진짜로 컴퓨터 이름인가?... 웹애플리케이션이 머신네임을 그냥 막 이렇게 찍는다고?...
    이때부터 멘붕이 왔습니다...
    심지어 어트리뷰트로 넘겨주지 않아도 userName은 잘 찍혔습니다. 대소문자 구분도 없이 말이죠. 마치 대소문자 구분이 없는 windows 시스템 환경변수처럼.... (참고: Model의 attribute는 대소문자 구분을 한다)
    😭...

    (문제 탐색 과정을 생략한) 문제 원인


    탐색 과정은 생략합니다. 삽질의 시간을 다 나열할 필요는 없을 것 같아서요.
    원인 1. 스프링부트는 애플리케이션을 시작할 때 getProperties()해서 Java system properties를 모두 읽어들인다(링크). 이것 자체만으론 문제가 안되지만...
    원인 2. mustache for java(구체적으로는 springboot를 위한 라이브러리)는 템플릿을 찾고 파싱하는 데에 reflection을 사용한다. 의도하진 않았겠지만, 애플리케이션이 당시 들고있는 자원에서도... system property도... 차별없이 너도 한방 나도 한방 찍어버린다...
    (썸네일처럼 JAVA_HOME도 찍어보고 path도 찍어보고 했는데 다 잘 나오더라고요. 그리고 사실 이것만이 문제가 아니었...지만 여백이 부족하여 적지 않는다(?))

    결론


    "아직 부트캠프에서 Spring boot도 헤매고 있는 나도 오픈소스 컨트리뷰터가 될 수 있을까?!?!"라는 희망으로 열심히 문제를 파봤지만...
    원인을 알아도 컨트리뷰팅 하는 것은 어려운 일이었습니다. 일단 의사표현을 하려면 영어를 해야하는데.. 나는 영알못이잖아? 안될거야 아마😭...

    그래서 이슈를 남기진 못했지만...

    1. 일단 mustache를 쓸 때는 조심히 쓰자. 다른 템플릿엔진도 이런 문제가 있을 수 있겠다. 확인하고 쓰자. 그런 생각을 했습니다.
    2. 결국 해당 attributeName은 "user_name"으로 써서 해결했습니다.
    3. "windows만 그렇고 mac은 괜찮아! 역시 개발은 mac이지!"라고 하시는 분도 계셨었는데 아닙니다. 그냥 OS에서 사용중인 환경변수명이 약간 다를 뿐이에요. 그쪽 변수명을 찍으면 그게 나올 겁니다. EC2 인스턴스에서도 똑같은 문제가 일어납니다. 그렇담 mac도 마찬가지겠죠.
    4. 다른 분들은 같은 고생을 하시지 않기를...... 혹시나 우연히 이 글을 보시고 영잘알이셔서 이슈를 넣는 분이 계시다면 꼭 좀 알려주세요. 조마조마한 마음으로 해당 라이브러리를 쓰지 않아도 되는 날이 오기를...

    댓글

Designed by Tistory.