Apache Tomcat의 보안 취약점(CVE-2020-1938)으로 인한 Ghostcat 공격이 올 수 있으니 취약 버전의 Tomcat을 업데이트 하거나 Tomcat의 AJP Connector 를 비활성화 하라는 권고를 받았다. 운영 중인 여러 사이트에 대해 조치 중 한 군데에서만 발생한 이슈가 있었고 경험을 정리하고자 한다.
사내에서 내가 관리하는 거의 모든 서비스가 이 버전 안에 속하는데, Tomcat 7 기준의 최신 버전은 7.0.103, Tomcat 8 기준의 최신 버전은 8.5.53 이다. 서버별로 접속해서 업그레이드를 했는데 한 사이트에서 파라미터 인코딩 문제가 발생했다. 7.0.103으로 버전업을 했더니 한글 파라미터가 깨지는 것이다.
Tomcat의 server.xml(conf/server.xml) 파일
확인했던 부분은 다음과 같다.
<Connector protocol="HTTP/1.1" URIEncoding="UTF-8"/>
<Connector protocol="AJP/1.3"
address="0.0.0.0"
URIEncoding="UTF-8"/>
URIEncoding="UTF-8"
설정은 거의 습관화가 되어 있어서 빠뜨리지 않았다.
요청 Parameter의 인코딩 확인
요청 파라미터의 인코딩을 확인하였다. 잘되던게 안되었던 것이라 어플리케이션의 문제는 아닐 것이라 생각했지만 확인차.
URLEncoder.encode("param", "UTF-8"); // java
로컬 환경에서의 동일버전 Tomcat 테스트
운영 Tomcat 버전과 동일한 버전을 세팅하고 설정도 동일하게 가져왔을 때 문제도 동일한지 확인하였다. 그런데 로컬환경에서는 정상적으로 작동한 것을 확인하고, 운영 환경의 문제에 문제가 있겠다는 단서를 얻었다. 정확히는 Tomcat 자체만의 문제가 아닌 것을 알 수 있었던 포인트였다.
Apache Httpd 서버 / mod jk 🤔
Tomcat의 문제가 아니라면 앞단의 웹 서버나 요청을 전달하는 mod jk 가 의심되었다. mod jk가 조금 더 의심되었는데, 다른 서비스 운영 환경과 지금 문제가 되는 서비스의 환경의 차이가 이것 뿐이었기 때문.
즉, 문제가 없는 환경은 Apache Httpd + mod_proxy -> Apache Tomcat 7.0.100(혹은 103) 이고, 현재는 mod_proxy 부분이 mod_jk로만 다를 뿐이었다.
참고 : Apache Httpd 는 2.2.14 / mod jk 는 1.2.37 이었다.
선택은?
1) mod_jk를 Tomcat 버전에 맞게 찾아서 업데이트 할 것이냐,
2) mod_proxy로 변경할 것이냐
의 2가지 선택지가 있었고, 난 후자를 선택했다. 애초에 Tomcat을 업데이트 하는 이유가 ajp 프로토콜의 취약점 때문이었는데 현재 mod_jk 는 ajp로 통신하고 있기도 했고, 이 모듈 사용을 위해서는 군더더기 설정 파일(workers.properties 등)을 가지고 있어야 하는 것도 마음에 안들었다. 또, 굳이 mod jk 를 고집하지 않아도 될 상황이었다.
mod_proxy 설정으로 변경(해결)
Apache httpd 서버에서 Tomcat 으로 요청을 전달하는 일을 mod_proxy가 하도록 변경했다. 다행히 이미 모듈은 설치되어 있어서 귀찮은 작업은 하지 않고 설정 세 줄만 추가하고 Apache httpd 재시작 후 테스트해보니 한글 파라미터가 깨짐 없이 작동했다.
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://locahost:8080/
ProxyVia On